This commit is contained in:
bdf1 2022-10-17 02:58:52 +13:00
commit a1eb7544bc
183 changed files with 70001 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
_saves/*

5
B站视频教程.url Normal file
View File

@ -0,0 +1,5 @@
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,2
[InternetShortcut]
IDList=
URL=https://www.bilibili.com/video/BV1SB4y1p7bg?spm_id_from=333.999.0.0

57
_codelab/L1.md Normal file
View File

@ -0,0 +1,57 @@
# 第一章伤害计算函数getDamageInfo
要求:读懂脚本编辑 - 伤害计算函数getDamageInfo的全部脚本代码无需理解支援的实现
回答如下几个问题:
1. 如下几个局部变量分别是什么意义?
`mon_atk`, `init_damage`, `per_damage`, `hero_per_damage`, `turn`, `damage`
2. 如何理解下面这几句话?
`if (core.hasSpecial(mon_special, 2)) per_damage = mon_atk;`
`var turn = Math.ceil(mon_hp / hero_per_damage);`
`var damage = init_damage + (turn - 1) * per_damage + turn * counterDamage;`
3. 负伤在哪里实现的?
依次实现如下几个怪物属性(仅允许修改`getDamageInfo`函数):
1. **闪避编号31** 受到伤害降低40%。
2. **穿刺编号32** 无视角色70%防御力。
3. **冰冻编号33** 怪物首先冰冻角色3回合冰冻期间每回合额外造成角色护盾的20%伤害。
4. **中子束编号34** 每回合普攻两次,魔攻一次。
5. **残暴斩杀编号35** 战斗开始时如果角色血量不大于怪物血量的200%,则直接暴毙。
6. **窥血为攻编号36** 战斗开始时自身攻击力变为角色当前生命值的10%,向下取整。
7. **匙之力编号37** 角色身上每存在一把黄钥匙最终伤害提升5%;蓝钥匙视为三把黄钥匙,红钥匙视为九把黄钥匙,线性叠加。
8. **崩甲编号38** 怪物每回合附加勇士战斗开始时的护盾数值的0.1倍作为伤害。
9. **混乱编号39** 战斗中,勇士攻防互换。
10. **强击编号40** 怪物第一回合三倍攻击。
11. **暗影庇护编号41** 处于无敌状态但每回合损耗自身2%的最大生命值。
再依次实现如下几个角色技能:
1. 角色每回合回复`flag:x1`%倍护盾的生命值。(如,`flag:x1`是10时每回合回复10%护盾值的生命)
2. 角色每回合造成和受到的伤害均提升`flag:x2`%。(如,`flag:x2`为10时每回合造成和受到伤害都提升10%
3. 角色攻击在战斗时减少`flag:x3`,防御力增加`flag:x3`。
4. 角色无视怪物的`flag:x4`%的防御力。(如,`flag:x4`是10时无视怪物的10%防御力)
5. 角色额外抢攻`flag:x5`回合。
[点此查看答案](L1_answer)

244
_codelab/L1_answer.md Normal file
View File

@ -0,0 +1,244 @@
```js
function (enemy, hero, x, y, floorId) {
// 获得战斗伤害信息(实际伤害计算函数)
//
// 参数说明:
// enemy该怪物信息
// hero勇士的当前数据如果对应项不存在则会从core.status.hero中取。
// x,y该怪物的坐标查看手册和强制战斗时为undefined
// floorId该怪物所在的楼层
// 后面三个参数主要是可以在光环等效果上可以适用
floorId = floorId || core.status.floorId;
var hero_hp = core.getRealStatusOrDefault(hero, 'hp'),
hero_atk = core.getRealStatusOrDefault(hero, 'atk'),
hero_def = core.getRealStatusOrDefault(hero, 'def'),
hero_mdef = core.getRealStatusOrDefault(hero, 'mdef'),
origin_hero_hp = core.getStatusOrDefault(hero, 'hp'),
origin_hero_atk = core.getStatusOrDefault(hero, 'atk'),
origin_hero_def = core.getStatusOrDefault(hero, 'def');
// 勇士的负属性都按0计算
hero_hp = Math.max(0, hero_hp);
hero_atk = Math.max(0, hero_atk);
hero_def = Math.max(0, hero_def);
hero_mdef = Math.max(0, hero_mdef);
// 怪物的各项数据
// 对坚固模仿等处理扔到了脚本编辑-getEnemyInfo之中
var enemyInfo = core.enemys.getEnemyInfo(enemy, hero, x, y, floorId);
var mon_hp = enemyInfo.hp,
mon_atk = enemyInfo.atk,
mon_def = enemyInfo.def,
mon_special = enemyInfo.special;
// 混乱编号39战斗中勇士攻防互换。
if (core.hasSpecial(mon_special, 39)) {
var temp = hero_atk;
hero_atk = hero_def;
hero_def = temp;
}
// 残暴斩杀编号35战斗开始时如果角色血量不大于怪物血量的200%,则直接暴毙。
if (core.hasSpecial(mon_special, 35) && hero_hp < mon_hp * 2) {
return null;
}
// 窥血为攻编号36战斗开始时自身攻击力变为角色当前生命值的10%,向下取整。
if (core.hasSpecial(mon_special, 36)) {
mon_atk = Math.floor(hero_hp / 10);
}
// 技能3角色攻击在战斗时减少`flag:x3`,防御力增加`flag:x3`。
if (core.getFlag('skill', 0) == 3) {
// 注意这里直接改变的面板攻击力(经过装备增幅后的)而不是基础攻击力。
hero_atk -= core.getFlag('x3', 0);
hero_def += core.getFlag('x3', 0);
}
// 技能4角色无视怪物的`flag:x4`%的防御力。(如,`flag:x4`是10时无视怪物的10%防御力)
if (core.getFlag('skill', 0) == 4) {
mon_def -= Math.floor(core.getFlag('x4', 0) / 100);
}
// 如果是无敌属性,且勇士未持有十字架
if (core.hasSpecial(mon_special, 20) && !core.hasItem("cross"))
return null; // 不可战斗
// 战前造成的额外伤害(可被护盾抵消)
var init_damage = 0;
// 吸血
if (core.hasSpecial(mon_special, 11)) {
var vampire_damage = hero_hp * enemy.value;
// 如果有神圣盾免疫吸血等可以在这里写
// 也可以用hasItem和hasEquip来判定装备
// if (core.hasFlag('shield5')) vampire_damage = 0;
vampire_damage = Math.floor(vampire_damage) || 0;
// 加到自身
if (enemy.add) // 如果加到自身
mon_hp += vampire_damage;
init_damage += vampire_damage;
}
// 每回合怪物对勇士造成的战斗伤害
var per_damage = mon_atk - hero_def;
// 魔攻:战斗伤害就是怪物攻击力
if (core.hasSpecial(mon_special, 2)) per_damage = mon_atk;
// 穿刺编号32无视角色70%防御力。
if (core.hasSpecial(mon_special, 32)) per_damage = Math.floor(mon_atk - 0.3 * hero_def);
// 战斗伤害不能为负值
if (per_damage < 0) per_damage = 0;
// 中子束编号34每回合普攻两次魔攻一次。
if (core.hasSpecial(mon_special, 34)) {
per_damage *= 2;
per_damage += mon_atk;
}
// 崩甲编号38怪物每回合附加勇士战斗开始时的护盾数值的0.1倍作为伤害。
if (core.hasSpecial(mon_special, 38)) {
per_damage += Math.floor(hero_mdef * 0.1);
}
// 2连击 & 3连击 & N连击
if (core.hasSpecial(mon_special, 4)) per_damage *= 2;
if (core.hasSpecial(mon_special, 5)) per_damage *= 3;
if (core.hasSpecial(mon_special, 6)) per_damage *= (enemy.n || 4);
// 每回合的反击伤害;反击是按照勇士的攻击次数来计算回合
var counterDamage = 0;
if (core.hasSpecial(mon_special, 8))
counterDamage += Math.floor((enemy.atkValue || core.values.counterAttack) * hero_atk);
// 先攻
if (core.hasSpecial(mon_special, 1)) init_damage += per_damage;
// 破甲
if (core.hasSpecial(mon_special, 7))
init_damage += Math.floor((enemy.defValue || core.values.breakArmor) * hero_def);
// 净化
if (core.hasSpecial(mon_special, 9))
init_damage += Math.floor((enemy.n || core.values.purify) * hero_mdef);
// 冰冻编号33怪物首先冰冻角色3回合冰冻期间每回合额外造成角色护盾的20%伤害。
if (core.hasSpecial(mon_special, 33)) {
init_damage += Math.floor(3 * (per_damage + 0.2 * hero_mdef));
}
// 勇士每回合对怪物造成的伤害
var hero_per_damage = Math.max(hero_atk - mon_def, 0);
// 技能2角色每回合造成和受到的伤害均提升`flag:x2`%。(如,`flag:x2`为10时每回合造成和受到伤害都提升10%
if (core.getFlag("skill", 0) == 2) {
per_damage += Math.floor(per_damage * core.getFlag('x2', 0) / 100);
hero_per_damage += Math.floor(hero_per_damage * core.getFlag('x2', 0) / 100);
}
// 闪避编号31受到伤害降低40%。
if (core.hasSpecial(mon_special, 31)) {
hero_per_damage = Math.floor(hero_per_damage * 0.6);
}
// 如果没有破防,则不可战斗
if (hero_per_damage <= 0) return null;
// 技能5角色额外抢攻`flag:x5`回合。
if (core.getFlag("skill", 0) == 5) {
mon_hp -= core.getFlag('x5', 0) * hero_per_damage;
// 判定是否已经秒杀 -> 注意mon_hp不能小于等于0否则回合计算会出问题
if (mon_hp <= 0) mon_hp = 1;
}
// 暗影庇护编号41处于无敌状态但每回合损耗自身2%的最大生命值。
if (core.hasSpecial(mon_special, 41)) {
hero_per_damage = Math.floor(mon_hp * 0.02);
}
// 强击编号40怪物第一回合三倍攻击。
// 注意:需要判定角色是否秒杀怪物
if (core.hasSpecial(mon_special, 40) && hero_per_damage < mon_hp) {
init_damage += 2 * mon_atk;
}
// 勇士的攻击回合数;为怪物生命除以每回合伤害向上取整
var turn = Math.ceil(mon_hp / hero_per_damage);
// ------ 支援 ----- //
// 这个递归最好想明白为什么flag:__extraTurn__是怎么用的
var guards = core.getFlag("__guards__" + x + "_" + y, enemyInfo.guards);
var guard_before_current_enemy = false; // ------ 支援怪是先打(true)还是后打(false)
turn += core.getFlag("__extraTurn__", 0);
if (guards.length > 0) {
if (!guard_before_current_enemy) { // --- 先打当前怪物,记录当前回合数
core.setFlag("__extraTurn__", turn);
}
// 获得那些怪物组成小队战斗
for (var i = 0; i < guards.length; i++) {
var gx = guards[i][0],
gy = guards[i][1],
gid = guards[i][2];
// 递归计算支援怪伤害信息这里不传x,y保证不会重复调用
// 这里的mdef传0因为护盾应该只会被计算一次
var info = core.enemys.getDamageInfo(core.material.enemys[gid], { hp: origin_hero_hp, atk: origin_hero_atk, def: origin_hero_def, mdef: 0 });
if (info == null) { // 小队中任何一个怪物不可战斗直接返回null
core.removeFlag("__extraTurn__");
return null;
}
// 已经进行的回合数
core.setFlag("__extraTurn__", info.turn);
init_damage += info.damage;
}
if (guard_before_current_enemy) { // --- 先打支援怪物,增加当前回合数
turn += core.getFlag("__extraTurn__", 0);
}
}
core.removeFlag("__extraTurn__");
// ------ 支援END ------ //
// 最终伤害:初始伤害 + 怪物对勇士造成的伤害 + 反击伤害
var damage = init_damage + (turn - 1) * per_damage + turn * counterDamage;
// 再扣去护盾
damage -= hero_mdef;
// 匙之力编号37角色身上每存在一把黄钥匙最终伤害提升5%;蓝钥匙视为三把黄钥匙,红钥匙视为九把黄钥匙,线性叠加。
// 需要判定是否负伤
if (core.hasSpecial(mon_special, 37) && damage > 0) {
var cnt = core.itemCount("yellowKey") + 3 * core.itemCount("blueKey") + 9 * core.itemCount("redKey");
damage += Math.floor(damage * 0.05 * cnt);
}
// 检查是否允许负伤
if (!core.flags.enableNegativeDamage)
damage = Math.max(0, damage);
// 最后处理仇恨和固伤(因为这两个不能被护盾减伤)
if (core.hasSpecial(mon_special, 17)) { // 仇恨
damage += core.getFlag('hatred', 0);
}
if (core.hasSpecial(mon_special, 22)) { // 固伤
damage += enemy.damage || 0;
}
// 技能1角色每回合回复`flag:x1`%倍护盾的生命值。(如,`flag:x1`是10时每回合回复10%护盾值的生命)
if (core.getFlag("skill", 0) == 1) {
damage -= Math.floor(core.getFlag('x1', 0) / 100 * hero_mdef * turn);
}
return {
"mon_hp": Math.floor(mon_hp),
"mon_atk": Math.floor(mon_atk),
"mon_def": Math.floor(mon_def),
"init_damage": Math.floor(init_damage),
"per_damage": Math.floor(per_damage),
"hero_per_damage": Math.floor(hero_per_damage),
"turn": Math.floor(turn),
"damage": Math.floor(damage)
};
}
```

102
_codelab/L2.md Normal file
View File

@ -0,0 +1,102 @@
# 第二章怪物特殊属性定义getSpecials表格配置
要求:读懂脚本编辑 - 怪物特殊属性定义getSpecials的实现。理解如何定义一个新的怪物属性。同时还需要理解如何给怪物表格增加新项目。
回答如下问题:
1. 如何定义一个新的怪物属性?
2. 如何取得当前怪物的各项数值?
3. 第五项参数在哪些情况下写1为什么需要
4. 如何给怪物表格定义新项目?如何在伤害计算等地方取用定义的新项目?
5. 当前,有一部分怪物属性使用了相同的表格项,如阻激夹域都使用了`value`等;这样无法同时给怪物增加吸血和领域两个属性。那应该怎么做才能同时支持这两项?
6. 理解《咕工智障》的下述怪物特殊属性并回答:
- 如果一个该属性怪物设置了`hpValue = 10, range = 2`,那么怪物手册中显示该怪物的特殊属性名和描述是什么?
- 如果一个该属性怪物设置了`hpValue = -20, defValue = 30`,那么怪物手册中显示该怪物的特殊属性名和描述是什么?
- 如果一个该属性怪物设置了`hpValue = 10, atkValue = 20, defValue = 30, add = true`,那么怪物手册中显示该怪物的特殊属性名和描述是什么?
- 如果怪物手册中的描述是`周围方形范围内5格的友军生命提升10%攻击降低20%,线性叠加`,那么该怪物的哪些项被设置了成了多少?该怪物的特殊属性名是什么?
- 如果怪物手册中的描述是`周围十字范围内3格的友军生命提升20%攻击提升10%防御提升5%,不可叠加`,那么该怪物的哪些项被设置了成了多少?该怪物的特殊属性名是什么?
```js
[25, function (enemy) {
if (enemy.auraName) return enemy.auraName;
if (enemy.hpValue && enemy.atkValue && enemy.defValue) return "魔力光环";
if (enemy.hpValue) {
if (enemy.hpValue > 0) return "活力光环";
return "懒散光环";
}
if (enemy.atkValue) {
if (enemy.atkValue > 0) return "狂暴光环";
return "静谧光环";
}
if (enemy.defValue) {
if (enemy.defValue > 0) return "坚毅光环";
return "软弱光环";
}
return "光环";
}, function (enemy) {
var str;
if (!enemy.range) {
str = "同楼层所有友军";
} else {
str = "周围" + (enemy.zoneSquare ? "方形" : "十字")
+ "范围内\r[yellow]" + (enemy.range || 1) + "\r格的友军";
}
if (enemy.hpValue) {
if (enemy.hpValue > 0) str += "生命提升\r[yellow]" + enemy.hpValue + "%\r";
else str += "生命降低\r[yellow]" + (-enemy.hpValue) + "%\r";
}
if (enemy.atkValue) {
if (enemy.atkValue > 0) str += "攻击提升\r[yellow]" + enemy.atkValue + "%\r";
else str += "攻击降低\r[yellow]" + (-enemy.atkValue) + "%\r";
}
if (enemy.defValue) {
if (enemy.defValue > 0) str += "防御提升\r[yellow]" + enemy.defValue + "%\r";
else str += "防御降低\r[yellow]" + (-enemy.defValue) + "%\r";
}
str += (enemy.add ? "线性叠加" : "不可叠加");
return str;
}, "#e6e099", 1],
```
7. 理解《咕工智障》的下述怪物特殊属性并回答:
- 吸血数值是如何计算在怪物手册之中的?
- 如何根据角色当前拥有的道具或者变量来修改怪物属性描述?
- 如果要让简单难度下,怪物吸血值减半,特殊属性定义中应该怎么修改?
```js
[11, "吸血", function (enemy) {
var str = "\r[\#e525ff]【红海技能】\r战斗前首先吸取对方的"
+ Math.floor(100 * enemy.value || 0) + "%生命(约"
+ Math.floor((enemy.value || 0) * core.getRealStatus('hp')) + "点)作为伤害"
+ (enemy.add ? ",并把伤害数值加到自身生命上" : "");
if (core.hasItem("I_noVampire")) str += "\r[yellow](对你无效)\r";
return str;
}, "#ff00d2"],
```
8. 定义同时满足如下条件的特殊属性(编号`28`),并和《咕工智障》的写法进行比较。
- 当怪物的 `value28 > 0` 时,特殊属性名为`迅捷光环`
- 当怪物的 `value28 <= 0` 时,特殊属性名为`怠惰光环`
- 当难度为简单(`flag:hard = 1`)时,描述为`此技能在简单难度下无效!`
- 当角色拥有道具 `I123` 时,描述为`此技能已被魔杖抵消!`
- 当怪物的 `range > 0` 时,描述存在`周围[方形/十字]范围内[?]格的友军`;其中这`[]`里面内容由怪物的 `zoneSquare``range` 决定。
- 当怪物的 `range = null` 时,描述存在`当前楼层的友军`
- 当怪物的 `value28 > 0` 时,描述存在`先攻X回合`其中X由`value28`决定(如,`value28 = 5`时,描述存在`先攻5回合`
- 当怪物的 `value28 <= 0` 时,描述存在`被先攻X回合`其中X由`value28`决定(如,`value28 = -5`时,描述存在`被先攻5回合`
9. 定义同时满足如下条件的特殊属性(编号`30`),并和《咕工智障》的写法进行比较。
- 特殊属性名:匙之力
- 当怪物的 `range > 0` 时,描述存在`周围[方形/十字]范围内[?]格内`;其中这`[]`里面内容由怪物的 `zoneSquare``range` 决定。
- 当怪物的 `range = null` 时,描述存在`同楼层内`
- 描述存在 `每存在一个黄钥匙生命增加X点攻击增加Y点防御增加Z点`,其中`X, Y, Z`由怪物的`value, atkValue, defValue`决定。如果其中某一项为0或null则不显示对应项。例如如果`value = 30, defValue = 20`则只显示`生命增加30点防御增加20点`
10. 将阻击、激光、领域、吸血所使用的特殊属性值(当前均为`value`)分离,并实现一个怪物同时拥有`阻击伤害100点激光伤害50点领域伤害200点且吸血20%`这四个特殊属性。
- 需在怪物手册正确显示
- 需正确实现对应的效果(需要修改`伤害计算getDamageInfo和阻激夹域伤害updateCheckBlock`两个函数)
[点此查看答案](L2_answer)

153
_codelab/L2_answer.md Normal file
View File

@ -0,0 +1,153 @@
1. 在怪物特殊属性中增加一行,分别定义特殊属性的数字、名字、描述、颜色,以及是否是地图类技能(如光环)。
2. 使用`function (enemy) {}`,里面可以取用`enemy.xxx`调用数值;例如`enemy.value`可以调用怪物的value值。
3. 仅在地图类技能时需要写1。当怪物的该项为1时意味着该怪物的技能是和地图上其他图块有关的而不是怪物自身独立的。例如先攻魔攻这些技能就是自身独立和地图上其他图块无关而光环匙之力根据周边钥匙数量提升属性等这些技能就是与地图上其他怪物有关的。
4. 点击「配置表格」,找到怪物相关项目,并照葫芦画瓢即可。常见写法如下。
```js
"value": {
"_leaf": true,
"_type": "textarea",
"_docs": "特殊属性数值",
"_data": "特殊属性的数值\n如领域/阻激/激光怪的伤害值;吸血怪的吸血比例;光环怪增加生命的比例"
},
```
5. 可定义不同项目如v1, v2, v3等分别表示伤害值然后修改特殊描述和实际效果以取用v1, v2, v3等来代替原来的value。参见第10题解答。
6.
- 活力光环周围十字范围内2格的友军生命提升10%,不可叠加。
- 懒散光环同楼层所有友军生命降低20%防御提升30%,不可叠加。(注意,不会显示坚毅光环!)
- 魔力光环同楼层所有友军生命提升10%攻击提升20%防御提升30%,线性叠加。
- range=5, zoneSquare = true, hpValue=10, atkValue=-20, add=true活力光环。
- range=3, hpValue = 20, atkValue = 10, defValue = 5魔力光环。
7.
- 直接使用`enemy.value`获得当前吸血比例,乘以玩家当前生命值`core.getRealStatus('hp')`获得吸血数值,并取整再显示。
- 可以通过额外的if来修改具体的描述。
- 可以在简单难度下将value减半以达到效果。
```js
[11, "吸血", function (enemy) {
var value = enemy.value || 0; // 怪物吸血比例
if (flags.hard == 1) value /= 2; // 简单难度下吸血值减半
// 使用局部变量 value 代替 enemy.value
var str = "\r[\#e525ff]【红海技能】\r战斗前首先吸取对方的"
+ Math.floor(100 * value) + "%生命(约"
+ Math.floor(value * core.getRealStatus('hp')) + "点)作为伤害"
+ (enemy.add ? ",并把伤害数值加到自身生命上" : "");
if (core.hasItem("I_noVampire")) str += "\r[yellow](对你无效)\r";
return str;
}, "#ff00d2"],
```
8.
```js
[28, function (enemy) {
if (enemy.value28 > 0) return "迅捷光环";
return "怠惰光环";
}, function (enemy) {
var str;
// 直接 return 可以不显示具体技能内容。
if (flags.hard == 1) return '此技能在简单难度下无效!';
if (core.hasItem('I123')) return '此技能已被魔杖抵消!';
if (!enemy.range) {
str = "同楼层所有友军";
} else {
str = "周围" + (enemy.zoneSquare ? "方形" : "十字") + "范围内\r[yellow]" + (enemy.range || 1) + "\r格的友军";
}
if (enemy.value28 > 0) {
str += "先攻\r[yellow]" + (enemy.value28 || 0) + "\r回合。";
} else {
str += "被先攻\r[yellow]" + (-enemy.value28 || 0) + "\r回合。";
}
return str;
}, "#00dd00", 1],
```
9.
```js
[30, "匙之力", function (enemy) {
var str = "";
if (enemy.range) {
str += "周围" + (enemy.zoneSquare ? "方形" : "十字") + "范围内\r[yellow]" + enemy.range + "\r格每存在一把黄钥匙";
}
else str += "同楼层每存在一把黄钥匙,";
if (enemy.value) str += "生命增加\r[yellow]" + enemy.value + "\r点";
if (enemy.atkValue) str += "攻击增加\r[yellow]" + enemy.atkValue + "\r点";
if (enemy.defValue) str += "防御增加\r[yellow]" + enemy.defValue + "\r点";
str += "线性叠加。1把蓝钥匙=3把黄钥匙1把红钥匙=10把黄钥匙。";
return str;
}, "#A0A000", 1],
```
10. 使用配置表格增设如下项目也可以使用更好的名称如laserValue
```js
"v1": {
"_leaf": true,
"_type": "textarea",
"_docs": "阻击伤害"
},
"v2": {
"_leaf": true,
"_type": "textarea",
"_docs": "激光伤害"
},
"v3": {
"_leaf": true,
"_type": "textarea",
"_docs": "领域伤害"
},
"v4": {
"_leaf": true,
"_type": "textarea",
"_docs": "吸血比例"
},
```
然后特殊描述可以如下修改分别使用v1, v2, v3, v4代替value
```js
[11, "吸血", function (enemy) { return "战斗前,怪物首先吸取角色的" + Math.floor(100 * enemy.v4 || 0) + "%生命(约" + Math.floor((enemy.v4 || 0) * core.getStatus('hp')) + "点)作为伤害" + (enemy.add ? ",并把伤害数值加到自身生命上" : ""); }, "#dd4448"],
[15, "领域", function (enemy) { return "经过怪物周围" + (enemy.zoneSquare ? "九宫格" : "十字") + "范围内" + (enemy.range || 1) + "格时自动减生命" + (enemy.v3 || 0) + "点"; }, "#c677dd"],
[18, "阻击", function (enemy) { return "经过怪物周围" + (enemy.zoneSquare ? "九宫格" : "十字") + "时自动减生命" + (enemy.v1 || 0) + "点,同时怪物后退一格"; }, "#8888e6"],
[24, "激光", function (enemy) { return "经过怪物同行或同列时自动减生命" + (enemy.v2 || 0) + "点"; }, "#dda0dd"],
```
最后,修改实际效果。
```js
// 吸血getDamageInfo节选
if (core.hasSpecial(mon_special, 11)) {
/** 使用enemy.v4替代enemy.value **/
var vampire_damage = hero_hp * enemy.v4;
// 如果有神圣盾免疫吸血等可以在这里写
// 也可以用hasItem和hasEquip来判定装备
// if (core.hasFlag('shield5')) vampire_damage = 0;
vampire_damage = Math.floor(vampire_damage) || 0;
// 加到自身
if (enemy.add) // 如果加到自身
mon_hp += vampire_damage;
init_damage += vampire_damage;
}
```
```js
// 领域updateCheckBlock节选
for (var dx = -range; dx <= range; dx++) {
for (var dy = -range; dy <= range; dy++) {
if (dx == 0 && dy == 0) continue;
var nx = x + dx,
ny = y + dy,
currloc = nx + "," + ny;
if (nx < 0 || nx >= width || ny < 0 || ny >= height) continue;
// 如果是十字领域,则还需要满足 |dx|+|dy|<=range
if (!zoneSquare && Math.abs(dx) + Math.abs(dy) > range) continue;
/** 使用enemy.v3替代enemy.value **/
damage[currloc] = (damage[currloc] || 0) + (enemy.v3 || 0);
type[currloc] = type[currloc] || {};
type[currloc]["领域伤害"] = true;
}
}
```
激光和阻击同领域实现。

38
_codelab/L3.md Normal file
View File

@ -0,0 +1,38 @@
# 第三章怪物真实属性获取getEnemyInfo
要求:读懂脚本编辑 - 怪物真实属性getEnemyInfo的实现无需理解支援。理解如何动态修改怪物的三维理解光环效果的实现并知晓如何新增光环效果理解如何定义新变量并在getDamageInfo中取用。
回答如下问题:
1. 为什么要存在`getEnemyInfo`函数以获得怪物真实属性?所有东西都写在`getDamageInfo`里面不好吗?
2. 实现**仿攻编号45**:怪物攻击不低于勇士攻击。
3. 实现**窥血为攻编号36** 战斗开始时自身攻击力变为角色当前生命值的10%,向下取整。这种写法比第一章中在`getDamageInfo`中写法效果更好,为什么?
4. 仅修改`getEnemyInfo`,实现一个怪物`E345`满足:
- 简单难度flag:hard==1无特殊属性。
- 普通难度flag:hard==2拥有先攻属性。
- 困难难度flag:hard==3拥有三连击属性。
- 噩梦难度flag:hard==4同时拥有先攻、魔攻、二连击属性。
- 如果玩家拥有道具`I123`,则直接无视此怪物所有属性。
5. 仅修改`getEnemyInfo`,实现一个道具`I234`**当玩家持有此道具时怪物的血攻防均降低10%。**
6. 仅修改`getEnemyInfo`,实现特殊属性 **「上位压制」特殊编号46**:玩家每低于怪物一个等级(通过`core.getStatus('lv')`获得当前玩家等级,通过`enemy.level`获得该怪物的等级怪物三维提升10%玩家每高于怪物一个等级怪物三维降低5%。
7. 解释光环的缓存原理。为什么光环需要缓存?
8. `index`是什么意思? `var cache = core.status.checkBlock.cache[index];` 是干什么的?
9. 在默认光环的实现中,`hp_buff`, `atk_buff`, `def_buff`, `usedEnemyIds` 分别是干什么的?
10. 在默认光环的实现中,怪物属性的`value`, `atkValue`和`defValue`用于控制怪物的比例增幅。将其效果修改成数值增幅(例如 `value = 50` 表示生命提升50点而不是50%)。
11. 局部光环的实现原理是什么?十字和九宫格光环是如何区分的?
12. 实现 **「协同作战」特殊属性47**:同楼层/周围X格由range和zoneSquare决定每存在一个该属性的队友包括自身生命和攻防对应比例提升提升比例由怪物value, atkValue, defValue决定线性叠加。并在游戏中实际验证效果。注意这个效果和默认光环的区别
13. 实现 **「迅捷光环」特殊属性28**:同楼层/周围X格由range和zoneSquare决定的怪物额外先攻X回合由此怪物的value28决定。并在游戏中实际验证效果。
14. 实现 **「吸血光环」特殊属性48**:同楼层/周围X格由range和zoneSquare决定的怪物拥有「吸血」特殊属性吸血比例由光环怪的`vampireValue`项决定。并在游戏中实际验证效果。

4
_codelab/_sidebar.md Normal file
View File

@ -0,0 +1,4 @@
- [第一章:伤害计算函数](L1)
- [第二章:特殊属性定义,表格配置](L2)
- [第三章:怪物真实属性](L3)

2
_codelab/docsify.min.js vendored Normal file

File diff suppressed because one or more lines are too long

86
_codelab/index.html Normal file
View File

@ -0,0 +1,86 @@
<!DOCTYPE html>
<html lang="ch_ZN">
<head>
<meta charset="UTF-8">
<title>HTML5魔塔样板JS进阶</title>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="description" content="Description">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<link href="vue.css" rel="stylesheet">
</head>
<body>
<div id="app"></div>
<xml id="toolbox" style="display:none"></xml>
<div id="blocklyArea" style="opacity: 0;z-index: -1;"><div id="blocklyDiv"></div></div>
<textarea id="codeArea" style="display:none" spellcheck="false"></textarea>
<script>
window.$docsify = {
homepage: 'L1.md',
loadSidebar: true,
name: 'HTML5魔塔样板',
repo: 'https://github.com/ckcz123/mota-js',
// basepath: '../docs/',
// Search Support
search: {
maxAge: 43200000, // 过期时间,单位毫秒,默认一天
paths: 'auto',
placeholder: {
'/': '搜索文档...',
},
noData: {
'/': '找不到结果',
},
},
// load sidebar from _sidebar.md
loadSidebar: '_sidebar',
subMaxLevel: 2,
autoHeader: true,
auto2top: true,
mergeNavbar: true,
formatUpdated: '{YYYY}-{MM}-{DD} {HH}:{mm}:{ss}',
plugins: [
/*
function(hook){
var renderScriptNode=function(str){
return str.replace(/```.*?\r?\n['"]run['"];[^]*?\r?\n```/g,function(x){
return eval(`(function(){${x.replace(/```.*?\r?\n['"]run['"];/,'').slice(0,-3)}})()`)
})
}
var renderMotaAction=function(str){
return str.replace(bg.pattern,function(x){
return bg.replaceFunc(x)
})
}
hook.beforeEach(function(content){
return renderMotaAction(renderScriptNode(
content
))
})
hook.doneEach(function(){
var map=bg.replaceToken
var node=document.querySelector('.markdown-section')
var str=node.innerHTML
for(var id in map){
str=str.replace(id,map[id])
}
node.innerHTML=str
})
}
*/
]
}
</script>
<!-- 为了保证时序用脚本加载这两个 -->
<script src="docsify.min.js"></script>
</body>
</html>

5
_codelab/index.md Normal file
View File

@ -0,0 +1,5 @@
# H5脚本进阶顺序
```
伤害计算 - 战后 - 自绘状态栏 - 其他脚本编辑如检查地图伤害 - 插件中简单的复写libs - 自己根据API写插件函数 - 使用register系列注册点击和动画等 - 啃libs的实现 - 啃编辑器
```

1
_codelab/vue.css Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,57 @@
MIT License
Copyright (C) 2017 by Marijn Haverbeke <marijnh@gmail.com> and others
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
----------------------------------------------------------------
The MIT License (MIT)
Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------
MIT License
Copyright (C) 2013 by Marijn Haverbeke and others <marijnh@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

6
_server/CodeMirror/acorn.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
_server/CodeMirror/beautify.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,552 @@
/* ========== CodeMirror.css ========= */
.CodeMirror {
/* Set height, width, borders, and global font properties here */
font-family: monospace;
height: 300px;
direction: ltr;
}
/* PADDING */
.CodeMirror-lines {
padding: 4px 0; /* Vertical padding around content */
}
.CodeMirror pre {
padding: 0 4px; /* Horizontal padding of content */
}
/* GUTTER */
.CodeMirror-gutters {
white-space: nowrap;
}
.CodeMirror-linenumber {
padding: 0 3px 0 5px;
min-width: 20px;
text-align: right;
white-space: nowrap;
}
/* CURSOR */
.CodeMirror-cursor {
border-right: none;
width: 0;
}
.cm-fat-cursor .CodeMirror-cursor {
width: auto;
border: 0 !important;
}
.cm-fat-cursor div.CodeMirror-cursors {
z-index: 1;
}
.cm-fat-cursor-mark {
-webkit-animation: blink 1.06s steps(1) infinite;
-moz-animation: blink 1.06s steps(1) infinite;
animation: blink 1.06s steps(1) infinite;
}
.cm-animate-fat-cursor {
width: auto;
border: 0;
-webkit-animation: blink 1.06s steps(1) infinite;
-moz-animation: blink 1.06s steps(1) infinite;
animation: blink 1.06s steps(1) infinite;
}
@-moz-keyframes blink {
0% {
}
50% {
background-color: transparent;
}
100% {
}
}
@-webkit-keyframes blink {
0% {
}
50% {
background-color: transparent;
}
100% {
}
}
@keyframes blink {
0% {
}
50% {
background-color: transparent;
}
100% {
}
}
/* Can style cursor different in overwrite (non-insert) mode */
.cm-tab {
display: inline-block;
text-decoration: inherit;
}
.CodeMirror-rulers {
position: absolute;
left: 0;
right: 0;
top: -50px;
bottom: -20px;
overflow: hidden;
}
.CodeMirror-ruler {
top: 0;
bottom: 0;
position: absolute;
}
/* DEFAULT THEME */
.cm-header, .cm-strong {
font-weight: bold;
}
.cm-em {
font-style: italic;
}
.cm-link {
text-decoration: underline;
}
.cm-strikethrough {
text-decoration: line-through;
}
.cm-s-default .cm-variable,
.cm-s-default .cm-punctuation,
.cm-s-default .cm-property,
.cm-s-default .cm-operator {
}
.CodeMirror-composing {
border-bottom: 2px solid;
}
/* STOP */
/* The rest of this file contains styles related to the mechanics of
the editor. You probably shouldn't touch them. */
.CodeMirror {
position: relative;
overflow: hidden;
}
.CodeMirror-scroll {
overflow: scroll !important; /* Things will break if this is overridden */
/* 30px is the magic margin used to hide the element's real scrollbars */
/* See overflow: hidden in .CodeMirror */
margin-bottom: -30px;
margin-right: -30px;
padding-bottom: 30px;
height: 100%;
outline: none; /* Prevent dragging from highlighting the element */
position: relative;
}
.CodeMirror-sizer {
position: relative;
border-right: 30px solid transparent;
}
/* The fake, visible scrollbars. Used to force redraw during scrolling
before actual scrolling happens, thus preventing shaking and
flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
position: absolute;
z-index: 6;
display: none;
}
.CodeMirror-vscrollbar {
right: 0;
top: 0;
overflow-x: hidden;
overflow-y: scroll;
}
.CodeMirror-hscrollbar {
bottom: 0;
left: 0;
overflow-y: hidden;
overflow-x: scroll;
}
.CodeMirror-scrollbar-filler {
right: 0;
bottom: 0;
}
.CodeMirror-gutter-filler {
left: 0;
bottom: 0;
}
.CodeMirror-gutters {
position: absolute;
left: 0;
top: 0;
min-height: 100%;
z-index: 3;
}
.CodeMirror-gutter {
white-space: normal;
height: 100%;
display: inline-block;
vertical-align: top;
margin-bottom: -30px;
}
.CodeMirror-gutter-wrapper {
position: absolute;
z-index: 4;
background: none !important;
border: none !important;
}
.CodeMirror-gutter-background {
position: absolute;
top: 0;
bottom: 0;
z-index: 4;
}
.CodeMirror-gutter-elt {
position: absolute;
cursor: default;
z-index: 4;
}
.CodeMirror-gutter-wrapper ::selection {
background-color: transparent
}
.CodeMirror-gutter-wrapper ::-moz-selection {
background-color: transparent
}
.CodeMirror-lines {
cursor: text;
min-height: 1px; /* prevents collapsing before first draw */
}
.CodeMirror pre {
/* Reset some styles that the rest of the page might have set */
-moz-border-radius: 0;
-webkit-border-radius: 0;
border-radius: 0;
border-width: 0;
background: transparent;
font-family: inherit;
font-size: inherit;
margin: 0;
white-space: pre;
word-wrap: normal;
line-height: inherit;
color: inherit;
z-index: 2;
position: relative;
overflow: visible;
-webkit-tap-highlight-color: transparent;
-webkit-font-variant-ligatures: contextual;
font-variant-ligatures: contextual;
}
.CodeMirror-wrap pre {
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal;
}
.CodeMirror-linebackground {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 0;
}
.CodeMirror-linewidget {
position: relative;
z-index: 2;
padding: 0.1px; /* Force widget margins to stay inside of the container */
}
.CodeMirror-widget {
}
.CodeMirror-rtl pre {
direction: rtl;
}
.CodeMirror-code {
outline: none;
}
/* Force content-box sizing for the elements where we expect it */
.CodeMirror-scroll,
.CodeMirror-sizer,
.CodeMirror-gutter,
.CodeMirror-gutters,
.CodeMirror-linenumber {
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.CodeMirror-measure {
position: absolute;
width: 100%;
height: 0;
overflow: hidden;
visibility: hidden;
}
.CodeMirror-cursor {
position: absolute;
pointer-events: none;
}
.CodeMirror-measure pre {
position: static;
}
div.CodeMirror-cursors {
visibility: hidden;
position: relative;
z-index: 3;
}
div.CodeMirror-dragcursors {
visibility: visible;
}
.CodeMirror-focused div.CodeMirror-cursors {
visibility: visible;
}
.CodeMirror-crosshair {
cursor: crosshair;
}
/* Used to force a border model for a node */
.cm-force-border {
padding-right: .1px;
}
@media print {
/* Hide the cursor when printing */
.CodeMirror div.CodeMirror-cursors {
visibility: hidden;
}
}
/* See issue #2901 */
.cm-tab-wrap-hack:after {
content: '';
}
/* Help users use markselection to safely style text background */
span.CodeMirror-selectedtext {
background: none;
}
/* ========= show-hint.css ========= */
.CodeMirror-hints {
position: absolute;
z-index: 340;
overflow: hidden;
list-style: none;
margin: 0;
padding: 2px;
border-radius: 3px;
font-size: 90%;
font-family: monospace;
max-height: 20em;
overflow-y: auto;
}
.CodeMirror-hint {
margin: 0;
padding: 0 4px;
border-radius: 2px;
white-space: pre;
cursor: pointer;
}
/* ========= lint.css ========= */
/* The lint marker gutter */
.CodeMirror-lint-markers {
width: 16px;
}
.CodeMirror-lint-tooltip {
border-radius: 4px 4px 4px 4px;
font-family: monospace;
font-size: 10pt;
overflow: hidden;
padding: 2px 5px;
position: fixed;
white-space: pre;
white-space: pre-wrap;
z-index: 330;
max-width: 600px;
opacity: 0;
transition: opacity .4s;
-moz-transition: opacity .4s;
-webkit-transition: opacity .4s;
-o-transition: opacity .4s;
-ms-transition: opacity .4s;
}
.CodeMirror-lint-mark-error, .CodeMirror-lint-mark-warning {
background-position: left bottom;
background-repeat: repeat-x;
}
.CodeMirror-lint-marker-error, .CodeMirror-lint-marker-warning {
background-position: center center;
background-repeat: no-repeat;
cursor: pointer;
display: inline-block;
height: 16px;
width: 16px;
vertical-align: middle;
position: relative;
}
.CodeMirror-lint-message-error, .CodeMirror-lint-message-warning {
padding-left: 18px;
background-position: top left;
background-repeat: no-repeat;
}
.CodeMirror-lint-marker-multiple {
background-repeat: no-repeat;
background-position: right bottom;
width: 100%;
height: 100%;
}
/* ========= dialog.css ========= */
.CodeMirror-dialog {
position: absolute;
left: 0; right: 0;
background: inherit;
z-index: 15;
padding: .1em .8em;
overflow: hidden;
color: inherit;
}
.CodeMirror-dialog-top {
top: 0;
}
.CodeMirror-dialog-bottom {
bottom: 0;
}
.CodeMirror-dialog input {
border: none;
outline: none;
background: transparent;
width: 20em;
color: inherit;
font-family: monospace;
}
.CodeMirror-dialog button {
font-size: 70%;
}
/* ========= tern.css ========= */
.CodeMirror-Tern-completion {
padding-left: 22px;
position: relative;
line-height: 1.5;
}
.CodeMirror-Tern-completion:before {
position: absolute;
left: 2px;
bottom: 2px;
border-radius: 50%;
font-size: 12px;
font-weight: bold;
height: 15px;
width: 15px;
line-height: 16px;
text-align: center;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.CodeMirror-Tern-tooltip {
border-radius: 3px;
padding: 2px 5px;
font-size: 90%;
font-family: monospace;
white-space: pre-wrap;
max-width: 40em;
position: absolute;
z-index: 320;
transition: opacity 1s;
-moz-transition: opacity 1s;
-webkit-transition: opacity 1s;
-o-transition: opacity 1s;
-ms-transition: opacity 1s;
}
.CodeMirror-Tern-hint-doc {
max-width: 25em;
margin-top: -3px;
}
.CodeMirror-Tern-farg-current { text-decoration: underline; }
.CodeMirror-Tern-fhint-guess { opacity: .7; }
.CodeMirror-foldmarker {
font-family: arial;
line-height: .3;
cursor: pointer;
}
.CodeMirror-foldgutter {
width: .7em;
}
.CodeMirror-foldgutter-open,
.CodeMirror-foldgutter-folded {
cursor: pointer;
}
.CodeMirror-foldgutter-open:after {
content: "\25BE";
}
.CodeMirror-foldgutter-folded:after {
content: "\25B8";
}

4130
_server/CodeMirror/defs.js Normal file

File diff suppressed because it is too large Load Diff

1
_server/CodeMirror/jshint.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
_server/CodeMirror/tern.min.js vendored Normal file

File diff suppressed because one or more lines are too long

4242
_server/MotaAction.g4 Normal file

File diff suppressed because it is too large Load Diff

1737
_server/MotaActionParser.js Normal file

File diff suppressed because it is too large Load Diff

273
_server/README.md Normal file
View File

@ -0,0 +1,273 @@
# editor
直接使用游戏运行时(之后简称core)的代码来绘制游戏画面, 借助fs.js来实现浏览器编辑文件. 通过表格编辑数据, blockly图块编辑事件, code mirror编辑文本的可视化魔塔编辑器.
![](img_md/view1.png)
左侧数据区, 中间地图区, 右侧素材区
![](img_md/view2.png)
事件编辑器
![](img_md/view3.png)
脚本编辑器
> 此文件是editor的结构说明, 不是使用文档
## 组成
本目录下所有文件,以及`../editor.html`,`../editor-mobile.html`和`../启动服务.exe`,`../server.py`是地图编辑器的所有组件.
### 父目录
+ editor(-mobile).html
编辑器的[入口页面](http://127.0.0.1:1055/editor.html)
以`display:none`的形式引入了core的`index.html`的`dom`,修改了原来的`.gameCanvas #ui #data`等的名字以避免冲突
+ 启动服务.exe [源码](http://github.com/ckcz123/mota-js-server/)
为fs.js提供后端支持, 同时集成了一些实用工具
+ server.py
非windows平台中为fs.js提供后端支持
### core
游戏运行时中部分代码根据`main.mod=='editor'`进行了调整
+ 通过`main.init('editor')`加载数据
+ `editor`模式关闭了部分动画
+ `core.drawMap`中`editor`模式下不再画图,而是生成画图的函数提+ 供给`editor`
+ `editor`模式下`GlobalAnimate`可以独立的选择是否播放
+ `core.playBgm`和`core.playSound`中非`play`模式不再播放声音
+ `core.show`和`core.hide`中非`play`模式不再进行动画而是立刻+ 完成并执行回调
+ `editor`模式不执行`core.resize`
### fs.js
依照[issue#31](https://github.com/ckcz123/mota-js/issues/13)的约定, 模仿node的fs模块提供如下api,与`启动服务.exe`,`server.py`配合为js提供文件读写功能, 是编辑器成立的前提
``` js
fs.readFile('file.in','utf-8',callback)
//读文本文件
//callback:function(err, data)
//data:字符串
fs.readFile('file.in','base64',callback)
//读二进制文件
//callback:function(err, data)
//data:base64字符串
fs.writeFile('file.out', data ,'utf-8', callback)
//写文本文件
//callback:function(err)
//data:字符串
fs.writeFile('file.out', data ,'base64', callback)
//写二进制文件
//callback:function(err)
//data:base64字符串
fs.readdir(path, callback)
//callback:function(err, data)
//path:支持"/"做分隔符
//data:[filename1,filename2,..] filename是字符串,只包含文件不包含目录
//所有参数不允许缺省
```
### editor_multi.js
用[CodeMirror](https://github.com/codemirror/CodeMirror) 实现有高亮的多行文本编辑
编辑选定`id_`的文本域
``` js
editor_multi.import(id_,{lint:true})
```
编辑blockly方块的特定域
``` js
editor_multi.multiLineEdit(value,b,f,{lint:true},callback)
```
配置表格
``` js
editor_multi.editCommentJs(mod)
```
### MotaAction.g4
通过[antlr-blockly](https://github.com/zhaouv/antlr-blockly)的语法定义core中各事件对应的方块.
借助google的[blockly](https://github.com/google/blockly)来实现事件的可视化编辑.
入口方块以`_m`结尾
一般语句写在`action`中, 以`_s`结尾
### editor_blockly.js
把选定`id_`的事件用blockly编辑
``` js
editor_blockly.import(id_,{type:'event'});
```
把文本区域的代码转换成图块
``` js
editor_blockly.parse();
```
`initscript中`的`toolboxObj`定义了侧边栏中显示的图块
自定义`Blockly.FieldColour.prototype.createWidget_`修改了颜色选择器的行为
自定义`Blockly.FieldTextInput.prototype.showInlineEditor_`添加了自动补全
### editor_mode.js
用于切换数据区
加载数据
```javascript
editor.mode.loc();
editor.mode.enemyitem();
editor.mode.floor();
editor.mode.tower();
editor.mode.functions();
```
切换模式
```javascript
editor.mode.onmode('');//清空
editor.mode.onmode('save');//保存
editor.mode.onmode('nextChange');//下次onmode时前端进行切换
editor.mode.onmode('loc');
editor.mode.onmode('enemyitem');
editor.mode.onmode('floor');
editor.mode.onmode('tower');
editor.mode.onmode('functions');
editor.mode.onmode('map');
editor.mode.onmode('appendpic');
```
在`onmode('save')`时,改动才会保存到文件,涉及到图片的改动需要刷新页面使得`editor`能看到
数据区一些通用的函数也定义在这里
### editor_table.js
处理表格的生成, 及其响应的事件
其接受来自../project/\*.js的数据`obj`和来自table/\*.comment.js的注释`commentObj`
commentObj的结构如示例
``` js
{
"_type": "object",
"_data": {
"events": {
"_type": "object",
"_data": {
"resetGame": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "重置整个游戏"
},
"setInitData": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "设置初始属性"
},
```
一层正常数据, 一层`_`开头的结构说明, 忽略`_`层的话与obj同结构
通过
``` js
editor.table.objToTable(obj, commentObj)
editor.table.objToTr
editor.table.objToTd
```
遍历这两个对象来生成表格, 叶节点根据`_type`渲染成对应的dom
表格的值变化`onchange`, 双击`dblclickfunc`, 删除`deletefunc`, 添加`addfunc`也定义在此文件
### editor_mappanel.js
与地图区相关的功能
+ 画地图 线/矩形/tileset
+ 通过地图选中事件或素材
+ 右键菜单
+ 切换楼层
+ 大地图移动可视窗口
### editor_materialpanel.js
与素材区相关的功能
+ 选中
+ 展开/折叠
### editor_datapanel.js
与数据区相关的功能 (且与表格无关的功能)
+ 地图编辑
- 创建新地图
- 批量创建
+ 地图选点
+ 图块属性
- 注册素材
- 修改id
+ 楼层属性
- 修改楼层id
+ 全塔属性
+ 脚本编辑
+ 追加素材
- 选择导入的区域
- 导入图片
- 改色相
- 选中图片中的格子
- 确认追加
+ 公共事件
+ 插件编写
### editor_ui.js
ui事件中没有具体到前三个区中的函数
+ 响应点击
+ 快捷键
+ 显示帮助
+ UI预览 & 地图选点相关
### editor_util.js
一些通用的函数
+ 生成id
+ HTML转义
+ 像素处理
+ base64的encode/decode
+ 检查值是否为空
### editor_listen.js
界面与功能的绑定
### editor_file.js
包装fs.js, 把数据读写到对应的文件
### editor_game.js
游戏数据的处理
此部分的重构未完成, 实际上是由editor_file.js和editor_file_unsorted.js来做的
### editor.js
初始化加整合各模块
现状是还放了一些游戏数据有关的函数未挪到editor_game, 以及部分和入口页面生成有关的函数

File diff suppressed because one or more lines are too long

177
_server/blockly/LICENSE Normal file
View File

@ -0,0 +1,177 @@
Apache License
Version 2.0, January 2011
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

13
_server/blockly/NOTICE.md Normal file
View File

@ -0,0 +1,13 @@
# NOTICE
files
`blockly_compressed.js`
`blocks_compressed.js`
`javascript_compressed.js`
`zh-hans.js`
`media/*`
copyed from
https://github.com/google/blockly.git
`Converter.bundle.min.js`
copyed from
https://github.com/zhaouv/antlr-blockly.git

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,169 @@
// Do not edit this file; automatically generated by gulp.
'use strict';
Blockly.Blocks.colour={};Blockly.Constants={};Blockly.Constants.Colour={};Blockly.Constants.Colour.HUE=20;
Blockly.defineBlocksWithJsonArray([{type:"colour_picker",message0:"%1",args0:[{type:"field_colour",name:"COLOUR",colour:"#ff0000"}],output:"Colour",helpUrl:"%{BKY_COLOUR_PICKER_HELPURL}",style:"colour_blocks",tooltip:"%{BKY_COLOUR_PICKER_TOOLTIP}",extensions:["parent_tooltip_when_inline"]},{type:"colour_random",message0:"%{BKY_COLOUR_RANDOM_TITLE}",output:"Colour",helpUrl:"%{BKY_COLOUR_RANDOM_HELPURL}",style:"colour_blocks",tooltip:"%{BKY_COLOUR_RANDOM_TOOLTIP}"},{type:"colour_rgb",message0:"%{BKY_COLOUR_RGB_TITLE} %{BKY_COLOUR_RGB_RED} %1 %{BKY_COLOUR_RGB_GREEN} %2 %{BKY_COLOUR_RGB_BLUE} %3",
args0:[{type:"input_value",name:"RED",check:"Number",align:"RIGHT"},{type:"input_value",name:"GREEN",check:"Number",align:"RIGHT"},{type:"input_value",name:"BLUE",check:"Number",align:"RIGHT"}],output:"Colour",helpUrl:"%{BKY_COLOUR_RGB_HELPURL}",style:"colour_blocks",tooltip:"%{BKY_COLOUR_RGB_TOOLTIP}"},{type:"colour_blend",message0:"%{BKY_COLOUR_BLEND_TITLE} %{BKY_COLOUR_BLEND_COLOUR1} %1 %{BKY_COLOUR_BLEND_COLOUR2} %2 %{BKY_COLOUR_BLEND_RATIO} %3",args0:[{type:"input_value",name:"COLOUR1",check:"Colour",
align:"RIGHT"},{type:"input_value",name:"COLOUR2",check:"Colour",align:"RIGHT"},{type:"input_value",name:"RATIO",check:"Number",align:"RIGHT"}],output:"Colour",helpUrl:"%{BKY_COLOUR_BLEND_HELPURL}",style:"colour_blocks",tooltip:"%{BKY_COLOUR_BLEND_TOOLTIP}"}]);Blockly.Blocks.lists={};Blockly.Constants.Lists={};Blockly.Constants.Lists.HUE=260;
Blockly.defineBlocksWithJsonArray([{type:"lists_create_empty",message0:"%{BKY_LISTS_CREATE_EMPTY_TITLE}",output:"Array",style:"list_blocks",tooltip:"%{BKY_LISTS_CREATE_EMPTY_TOOLTIP}",helpUrl:"%{BKY_LISTS_CREATE_EMPTY_HELPURL}"},{type:"lists_repeat",message0:"%{BKY_LISTS_REPEAT_TITLE}",args0:[{type:"input_value",name:"ITEM"},{type:"input_value",name:"NUM",check:"Number"}],output:"Array",style:"list_blocks",tooltip:"%{BKY_LISTS_REPEAT_TOOLTIP}",helpUrl:"%{BKY_LISTS_REPEAT_HELPURL}"},{type:"lists_reverse",
message0:"%{BKY_LISTS_REVERSE_MESSAGE0}",args0:[{type:"input_value",name:"LIST",check:"Array"}],output:"Array",inputsInline:!0,style:"list_blocks",tooltip:"%{BKY_LISTS_REVERSE_TOOLTIP}",helpUrl:"%{BKY_LISTS_REVERSE_HELPURL}"},{type:"lists_isEmpty",message0:"%{BKY_LISTS_ISEMPTY_TITLE}",args0:[{type:"input_value",name:"VALUE",check:["String","Array"]}],output:"Boolean",style:"list_blocks",tooltip:"%{BKY_LISTS_ISEMPTY_TOOLTIP}",helpUrl:"%{BKY_LISTS_ISEMPTY_HELPURL}"},{type:"lists_length",message0:"%{BKY_LISTS_LENGTH_TITLE}",
args0:[{type:"input_value",name:"VALUE",check:["String","Array"]}],output:"Number",style:"list_blocks",tooltip:"%{BKY_LISTS_LENGTH_TOOLTIP}",helpUrl:"%{BKY_LISTS_LENGTH_HELPURL}"}]);
Blockly.Blocks.lists_create_with={init:function(){this.setHelpUrl(Blockly.Msg.LISTS_CREATE_WITH_HELPURL);this.setStyle("list_blocks");this.itemCount_=3;this.updateShape_();this.setOutput(!0,"Array");this.setMutator(new Blockly.Mutator(["lists_create_with_item"]));this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP)},mutationToDom:function(){var a=Blockly.utils.xml.createElement("mutation");a.setAttribute("items",this.itemCount_);return a},domToMutation:function(a){this.itemCount_=parseInt(a.getAttribute("items"),
10);this.updateShape_()},decompose:function(a){var b=a.newBlock("lists_create_with_container");b.initSvg();for(var c=b.getInput("STACK").connection,d=0;d<this.itemCount_;d++){var e=a.newBlock("lists_create_with_item");e.initSvg();c.connect(e.previousConnection);c=e.nextConnection}return b},compose:function(a){var b=a.getInputTargetBlock("STACK");for(a=[];b;)a.push(b.valueConnection_),b=b.nextConnection&&b.nextConnection.targetBlock();for(b=0;b<this.itemCount_;b++){var c=this.getInput("ADD"+b).connection.targetConnection;
c&&-1==a.indexOf(c)&&c.disconnect()}this.itemCount_=a.length;this.updateShape_();for(b=0;b<this.itemCount_;b++)Blockly.Mutator.reconnect(a[b],this,"ADD"+b)},saveConnections:function(a){a=a.getInputTargetBlock("STACK");for(var b=0;a;){var c=this.getInput("ADD"+b);a.valueConnection_=c&&c.connection.targetConnection;b++;a=a.nextConnection&&a.nextConnection.targetBlock()}},updateShape_:function(){this.itemCount_&&this.getInput("EMPTY")?this.removeInput("EMPTY"):this.itemCount_||this.getInput("EMPTY")||
this.appendDummyInput("EMPTY").appendField(Blockly.Msg.LISTS_CREATE_EMPTY_TITLE);for(var a=0;a<this.itemCount_;a++)if(!this.getInput("ADD"+a)){var b=this.appendValueInput("ADD"+a).setAlign(Blockly.ALIGN_RIGHT);0==a&&b.appendField(Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH)}for(;this.getInput("ADD"+a);)this.removeInput("ADD"+a),a++}};
Blockly.Blocks.lists_create_with_container={init:function(){this.setStyle("list_blocks");this.appendDummyInput().appendField(Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD);this.appendStatementInput("STACK");this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP);this.contextMenu=!1}};
Blockly.Blocks.lists_create_with_item={init:function(){this.setStyle("list_blocks");this.appendDummyInput().appendField(Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE);this.setPreviousStatement(!0);this.setNextStatement(!0);this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP);this.contextMenu=!1}};
Blockly.Blocks.lists_indexOf={init:function(){var a=[[Blockly.Msg.LISTS_INDEX_OF_FIRST,"FIRST"],[Blockly.Msg.LISTS_INDEX_OF_LAST,"LAST"]];this.setHelpUrl(Blockly.Msg.LISTS_INDEX_OF_HELPURL);this.setStyle("list_blocks");this.setOutput(!0,"Number");this.appendValueInput("VALUE").setCheck("Array").appendField(Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST);this.appendValueInput("FIND").appendField(new Blockly.FieldDropdown(a),"END");this.setInputsInline(!0);var b=this;this.setTooltip(function(){return Blockly.Msg.LISTS_INDEX_OF_TOOLTIP.replace("%1",
b.workspace.options.oneBasedIndex?"0":"-1")})}};
Blockly.Blocks.lists_getIndex={init:function(){var a=[[Blockly.Msg.LISTS_GET_INDEX_GET,"GET"],[Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE,"GET_REMOVE"],[Blockly.Msg.LISTS_GET_INDEX_REMOVE,"REMOVE"]];this.WHERE_OPTIONS=[[Blockly.Msg.LISTS_GET_INDEX_FROM_START,"FROM_START"],[Blockly.Msg.LISTS_GET_INDEX_FROM_END,"FROM_END"],[Blockly.Msg.LISTS_GET_INDEX_FIRST,"FIRST"],[Blockly.Msg.LISTS_GET_INDEX_LAST,"LAST"],[Blockly.Msg.LISTS_GET_INDEX_RANDOM,"RANDOM"]];this.setHelpUrl(Blockly.Msg.LISTS_GET_INDEX_HELPURL);this.setStyle("list_blocks");
a=new Blockly.FieldDropdown(a,function(a){a="REMOVE"==a;this.getSourceBlock().updateStatement_(a)});this.appendValueInput("VALUE").setCheck("Array").appendField(Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST);this.appendDummyInput().appendField(a,"MODE").appendField("","SPACE");this.appendDummyInput("AT");Blockly.Msg.LISTS_GET_INDEX_TAIL&&this.appendDummyInput("TAIL").appendField(Blockly.Msg.LISTS_GET_INDEX_TAIL);this.setInputsInline(!0);this.setOutput(!0);this.updateAt_(!0);var b=this;this.setTooltip(function(){var a=
b.getFieldValue("MODE"),d=b.getFieldValue("WHERE"),e="";switch(a+" "+d){case "GET FROM_START":case "GET FROM_END":e=Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM;break;case "GET FIRST":e=Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST;break;case "GET LAST":e=Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST;break;case "GET RANDOM":e=Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM;break;case "GET_REMOVE FROM_START":case "GET_REMOVE FROM_END":e=Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM;break;case "GET_REMOVE FIRST":e=
Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST;break;case "GET_REMOVE LAST":e=Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST;break;case "GET_REMOVE RANDOM":e=Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM;break;case "REMOVE FROM_START":case "REMOVE FROM_END":e=Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM;break;case "REMOVE FIRST":e=Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST;break;case "REMOVE LAST":e=Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST;break;case "REMOVE RANDOM":e=
Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM}if("FROM_START"==d||"FROM_END"==d)e+=" "+("FROM_START"==d?Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP:Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP).replace("%1",b.workspace.options.oneBasedIndex?"#1":"#0");return e})},mutationToDom:function(){var a=Blockly.utils.xml.createElement("mutation");a.setAttribute("statement",!this.outputConnection);var b=this.getInput("AT").type==Blockly.INPUT_VALUE;a.setAttribute("at",b);return a},domToMutation:function(a){var b=
"true"==a.getAttribute("statement");this.updateStatement_(b);a="false"!=a.getAttribute("at");this.updateAt_(a)},updateStatement_:function(a){a!=!this.outputConnection&&(this.unplug(!0,!0),a?(this.setOutput(!1),this.setPreviousStatement(!0),this.setNextStatement(!0)):(this.setPreviousStatement(!1),this.setNextStatement(!1),this.setOutput(!0)))},updateAt_:function(a){this.removeInput("AT");this.removeInput("ORDINAL",!0);a?(this.appendValueInput("AT").setCheck("Number"),Blockly.Msg.ORDINAL_NUMBER_SUFFIX&&
this.appendDummyInput("ORDINAL").appendField(Blockly.Msg.ORDINAL_NUMBER_SUFFIX)):this.appendDummyInput("AT");var b=new Blockly.FieldDropdown(this.WHERE_OPTIONS,function(b){var c="FROM_START"==b||"FROM_END"==b;if(c!=a){var e=this.getSourceBlock();e.updateAt_(c);e.setFieldValue(b,"WHERE");return null}});this.getInput("AT").appendField(b,"WHERE");Blockly.Msg.LISTS_GET_INDEX_TAIL&&this.moveInputBefore("TAIL",null)}};
Blockly.Blocks.lists_setIndex={init:function(){var a=[[Blockly.Msg.LISTS_SET_INDEX_SET,"SET"],[Blockly.Msg.LISTS_SET_INDEX_INSERT,"INSERT"]];this.WHERE_OPTIONS=[[Blockly.Msg.LISTS_GET_INDEX_FROM_START,"FROM_START"],[Blockly.Msg.LISTS_GET_INDEX_FROM_END,"FROM_END"],[Blockly.Msg.LISTS_GET_INDEX_FIRST,"FIRST"],[Blockly.Msg.LISTS_GET_INDEX_LAST,"LAST"],[Blockly.Msg.LISTS_GET_INDEX_RANDOM,"RANDOM"]];this.setHelpUrl(Blockly.Msg.LISTS_SET_INDEX_HELPURL);this.setStyle("list_blocks");this.appendValueInput("LIST").setCheck("Array").appendField(Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST);
this.appendDummyInput().appendField(new Blockly.FieldDropdown(a),"MODE").appendField("","SPACE");this.appendDummyInput("AT");this.appendValueInput("TO").appendField(Blockly.Msg.LISTS_SET_INDEX_INPUT_TO);this.setInputsInline(!0);this.setPreviousStatement(!0);this.setNextStatement(!0);this.setTooltip(Blockly.Msg.LISTS_SET_INDEX_TOOLTIP);this.updateAt_(!0);var b=this;this.setTooltip(function(){var a=b.getFieldValue("MODE"),d=b.getFieldValue("WHERE"),e="";switch(a+" "+d){case "SET FROM_START":case "SET FROM_END":e=
Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM;break;case "SET FIRST":e=Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST;break;case "SET LAST":e=Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST;break;case "SET RANDOM":e=Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM;break;case "INSERT FROM_START":case "INSERT FROM_END":e=Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM;break;case "INSERT FIRST":e=Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST;break;case "INSERT LAST":e=Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST;
break;case "INSERT RANDOM":e=Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM}if("FROM_START"==d||"FROM_END"==d)e+=" "+Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP.replace("%1",b.workspace.options.oneBasedIndex?"#1":"#0");return e})},mutationToDom:function(){var a=Blockly.utils.xml.createElement("mutation"),b=this.getInput("AT").type==Blockly.INPUT_VALUE;a.setAttribute("at",b);return a},domToMutation:function(a){a="false"!=a.getAttribute("at");this.updateAt_(a)},updateAt_:function(a){this.removeInput("AT");
this.removeInput("ORDINAL",!0);a?(this.appendValueInput("AT").setCheck("Number"),Blockly.Msg.ORDINAL_NUMBER_SUFFIX&&this.appendDummyInput("ORDINAL").appendField(Blockly.Msg.ORDINAL_NUMBER_SUFFIX)):this.appendDummyInput("AT");var b=new Blockly.FieldDropdown(this.WHERE_OPTIONS,function(b){var c="FROM_START"==b||"FROM_END"==b;if(c!=a){var e=this.getSourceBlock();e.updateAt_(c);e.setFieldValue(b,"WHERE");return null}});this.moveInputBefore("AT","TO");this.getInput("ORDINAL")&&this.moveInputBefore("ORDINAL",
"TO");this.getInput("AT").appendField(b,"WHERE")}};
Blockly.Blocks.lists_getSublist={init:function(){this.WHERE_OPTIONS_1=[[Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START,"FROM_START"],[Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END,"FROM_END"],[Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST,"FIRST"]];this.WHERE_OPTIONS_2=[[Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START,"FROM_START"],[Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END,"FROM_END"],[Blockly.Msg.LISTS_GET_SUBLIST_END_LAST,"LAST"]];this.setHelpUrl(Blockly.Msg.LISTS_GET_SUBLIST_HELPURL);this.setStyle("list_blocks");
this.appendValueInput("LIST").setCheck("Array").appendField(Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST);this.appendDummyInput("AT1");this.appendDummyInput("AT2");Blockly.Msg.LISTS_GET_SUBLIST_TAIL&&this.appendDummyInput("TAIL").appendField(Blockly.Msg.LISTS_GET_SUBLIST_TAIL);this.setInputsInline(!0);this.setOutput(!0,"Array");this.updateAt_(1,!0);this.updateAt_(2,!0);this.setTooltip(Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP)},mutationToDom:function(){var a=Blockly.utils.xml.createElement("mutation"),
b=this.getInput("AT1").type==Blockly.INPUT_VALUE;a.setAttribute("at1",b);b=this.getInput("AT2").type==Blockly.INPUT_VALUE;a.setAttribute("at2",b);return a},domToMutation:function(a){var b="true"==a.getAttribute("at1");a="true"==a.getAttribute("at2");this.updateAt_(1,b);this.updateAt_(2,a)},updateAt_:function(a,b){this.removeInput("AT"+a);this.removeInput("ORDINAL"+a,!0);b?(this.appendValueInput("AT"+a).setCheck("Number"),Blockly.Msg.ORDINAL_NUMBER_SUFFIX&&this.appendDummyInput("ORDINAL"+a).appendField(Blockly.Msg.ORDINAL_NUMBER_SUFFIX)):
this.appendDummyInput("AT"+a);var c=new Blockly.FieldDropdown(this["WHERE_OPTIONS_"+a],function(c){var e="FROM_START"==c||"FROM_END"==c;if(e!=b){var d=this.getSourceBlock();d.updateAt_(a,e);d.setFieldValue(c,"WHERE"+a);return null}});this.getInput("AT"+a).appendField(c,"WHERE"+a);1==a&&(this.moveInputBefore("AT1","AT2"),this.getInput("ORDINAL1")&&this.moveInputBefore("ORDINAL1","AT2"));Blockly.Msg.LISTS_GET_SUBLIST_TAIL&&this.moveInputBefore("TAIL",null)}};
Blockly.Blocks.lists_sort={init:function(){this.jsonInit({message0:Blockly.Msg.LISTS_SORT_TITLE,args0:[{type:"field_dropdown",name:"TYPE",options:[[Blockly.Msg.LISTS_SORT_TYPE_NUMERIC,"NUMERIC"],[Blockly.Msg.LISTS_SORT_TYPE_TEXT,"TEXT"],[Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE,"IGNORE_CASE"]]},{type:"field_dropdown",name:"DIRECTION",options:[[Blockly.Msg.LISTS_SORT_ORDER_ASCENDING,"1"],[Blockly.Msg.LISTS_SORT_ORDER_DESCENDING,"-1"]]},{type:"input_value",name:"LIST",check:"Array"}],output:"Array",style:"list_blocks",
tooltip:Blockly.Msg.LISTS_SORT_TOOLTIP,helpUrl:Blockly.Msg.LISTS_SORT_HELPURL})}};
Blockly.Blocks.lists_split={init:function(){var a=this,b=new Blockly.FieldDropdown([[Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT,"SPLIT"],[Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST,"JOIN"]],function(b){a.updateType_(b)});this.setHelpUrl(Blockly.Msg.LISTS_SPLIT_HELPURL);this.setStyle("list_blocks");this.appendValueInput("INPUT").setCheck("String").appendField(b,"MODE");this.appendValueInput("DELIM").setCheck("String").appendField(Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER);this.setInputsInline(!0);this.setOutput(!0,
"Array");this.setTooltip(function(){var b=a.getFieldValue("MODE");if("SPLIT"==b)return Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT;if("JOIN"==b)return Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN;throw Error("Unknown mode: "+b);})},updateType_:function(a){if(this.getFieldValue("MODE")!=a){var b=this.getInput("INPUT").connection;b.setShadowDom(null);var c=b.targetBlock();c&&(b.disconnect(),c.isShadow()?c.dispose():this.bumpNeighbours())}"SPLIT"==a?(this.outputConnection.setCheck("Array"),this.getInput("INPUT").setCheck("String")):
(this.outputConnection.setCheck("String"),this.getInput("INPUT").setCheck("Array"))},mutationToDom:function(){var a=Blockly.utils.xml.createElement("mutation");a.setAttribute("mode",this.getFieldValue("MODE"));return a},domToMutation:function(a){this.updateType_(a.getAttribute("mode"))}};Blockly.Blocks.logic={};Blockly.Constants.Logic={};Blockly.Constants.Logic.HUE=210;
Blockly.defineBlocksWithJsonArray([{type:"logic_boolean",message0:"%1",args0:[{type:"field_dropdown",name:"BOOL",options:[["%{BKY_LOGIC_BOOLEAN_TRUE}","TRUE"],["%{BKY_LOGIC_BOOLEAN_FALSE}","FALSE"]]}],output:"Boolean",style:"logic_blocks",tooltip:"%{BKY_LOGIC_BOOLEAN_TOOLTIP}",helpUrl:"%{BKY_LOGIC_BOOLEAN_HELPURL}"},{type:"controls_if",message0:"%{BKY_CONTROLS_IF_MSG_IF} %1",args0:[{type:"input_value",name:"IF0",check:"Boolean"}],message1:"%{BKY_CONTROLS_IF_MSG_THEN} %1",args1:[{type:"input_statement",
name:"DO0"}],previousStatement:null,nextStatement:null,style:"logic_blocks",helpUrl:"%{BKY_CONTROLS_IF_HELPURL}",mutator:"controls_if_mutator",extensions:["controls_if_tooltip"]},{type:"controls_ifelse",message0:"%{BKY_CONTROLS_IF_MSG_IF} %1",args0:[{type:"input_value",name:"IF0",check:"Boolean"}],message1:"%{BKY_CONTROLS_IF_MSG_THEN} %1",args1:[{type:"input_statement",name:"DO0"}],message2:"%{BKY_CONTROLS_IF_MSG_ELSE} %1",args2:[{type:"input_statement",name:"ELSE"}],previousStatement:null,nextStatement:null,
style:"logic_blocks",tooltip:"%{BKYCONTROLS_IF_TOOLTIP_2}",helpUrl:"%{BKY_CONTROLS_IF_HELPURL}",extensions:["controls_if_tooltip"]},{type:"logic_compare",message0:"%1 %2 %3",args0:[{type:"input_value",name:"A"},{type:"field_dropdown",name:"OP",options:[["=","EQ"],["\u2260","NEQ"],["\u200f<","LT"],["\u200f\u2264","LTE"],["\u200f>","GT"],["\u200f\u2265","GTE"]]},{type:"input_value",name:"B"}],inputsInline:!0,output:"Boolean",style:"logic_blocks",helpUrl:"%{BKY_LOGIC_COMPARE_HELPURL}",extensions:["logic_compare",
"logic_op_tooltip"]},{type:"logic_operation",message0:"%1 %2 %3",args0:[{type:"input_value",name:"A",check:"Boolean"},{type:"field_dropdown",name:"OP",options:[["%{BKY_LOGIC_OPERATION_AND}","AND"],["%{BKY_LOGIC_OPERATION_OR}","OR"]]},{type:"input_value",name:"B",check:"Boolean"}],inputsInline:!0,output:"Boolean",style:"logic_blocks",helpUrl:"%{BKY_LOGIC_OPERATION_HELPURL}",extensions:["logic_op_tooltip"]},{type:"logic_negate",message0:"%{BKY_LOGIC_NEGATE_TITLE}",args0:[{type:"input_value",name:"BOOL",
check:"Boolean"}],output:"Boolean",style:"logic_blocks",tooltip:"%{BKY_LOGIC_NEGATE_TOOLTIP}",helpUrl:"%{BKY_LOGIC_NEGATE_HELPURL}"},{type:"logic_null",message0:"%{BKY_LOGIC_NULL}",output:null,style:"logic_blocks",tooltip:"%{BKY_LOGIC_NULL_TOOLTIP}",helpUrl:"%{BKY_LOGIC_NULL_HELPURL}"},{type:"logic_ternary",message0:"%{BKY_LOGIC_TERNARY_CONDITION} %1",args0:[{type:"input_value",name:"IF",check:"Boolean"}],message1:"%{BKY_LOGIC_TERNARY_IF_TRUE} %1",args1:[{type:"input_value",name:"THEN"}],message2:"%{BKY_LOGIC_TERNARY_IF_FALSE} %1",
args2:[{type:"input_value",name:"ELSE"}],output:null,style:"logic_blocks",tooltip:"%{BKY_LOGIC_TERNARY_TOOLTIP}",helpUrl:"%{BKY_LOGIC_TERNARY_HELPURL}",extensions:["logic_ternary"]}]);
Blockly.defineBlocksWithJsonArray([{type:"controls_if_if",message0:"%{BKY_CONTROLS_IF_IF_TITLE_IF}",nextStatement:null,enableContextMenu:!1,style:"logic_blocks",tooltip:"%{BKY_CONTROLS_IF_IF_TOOLTIP}"},{type:"controls_if_elseif",message0:"%{BKY_CONTROLS_IF_ELSEIF_TITLE_ELSEIF}",previousStatement:null,nextStatement:null,enableContextMenu:!1,style:"logic_blocks",tooltip:"%{BKY_CONTROLS_IF_ELSEIF_TOOLTIP}"},{type:"controls_if_else",message0:"%{BKY_CONTROLS_IF_ELSE_TITLE_ELSE}",previousStatement:null,
enableContextMenu:!1,style:"logic_blocks",tooltip:"%{BKY_CONTROLS_IF_ELSE_TOOLTIP}"}]);Blockly.Constants.Logic.TOOLTIPS_BY_OP={EQ:"%{BKY_LOGIC_COMPARE_TOOLTIP_EQ}",NEQ:"%{BKY_LOGIC_COMPARE_TOOLTIP_NEQ}",LT:"%{BKY_LOGIC_COMPARE_TOOLTIP_LT}",LTE:"%{BKY_LOGIC_COMPARE_TOOLTIP_LTE}",GT:"%{BKY_LOGIC_COMPARE_TOOLTIP_GT}",GTE:"%{BKY_LOGIC_COMPARE_TOOLTIP_GTE}",AND:"%{BKY_LOGIC_OPERATION_TOOLTIP_AND}",OR:"%{BKY_LOGIC_OPERATION_TOOLTIP_OR}"};
Blockly.Extensions.register("logic_op_tooltip",Blockly.Extensions.buildTooltipForDropdown("OP",Blockly.Constants.Logic.TOOLTIPS_BY_OP));
Blockly.Constants.Logic.CONTROLS_IF_MUTATOR_MIXIN={elseifCount_:0,elseCount_:0,suppressPrefixSuffix:!0,mutationToDom:function(){if(!this.elseifCount_&&!this.elseCount_)return null;var a=Blockly.utils.xml.createElement("mutation");this.elseifCount_&&a.setAttribute("elseif",this.elseifCount_);this.elseCount_&&a.setAttribute("else",1);return a},domToMutation:function(a){this.elseifCount_=parseInt(a.getAttribute("elseif"),10)||0;this.elseCount_=parseInt(a.getAttribute("else"),10)||0;this.rebuildShape_()},
decompose:function(a){var b=a.newBlock("controls_if_if");b.initSvg();for(var c=b.nextConnection,d=1;d<=this.elseifCount_;d++){var e=a.newBlock("controls_if_elseif");e.initSvg();c.connect(e.previousConnection);c=e.nextConnection}this.elseCount_&&(a=a.newBlock("controls_if_else"),a.initSvg(),c.connect(a.previousConnection));return b},compose:function(a){a=a.nextConnection.targetBlock();this.elseCount_=this.elseifCount_=0;for(var b=[null],c=[null],d=null;a;){switch(a.type){case "controls_if_elseif":this.elseifCount_++;
b.push(a.valueConnection_);c.push(a.statementConnection_);break;case "controls_if_else":this.elseCount_++;d=a.statementConnection_;break;default:throw TypeError("Unknown block type: "+a.type);}a=a.nextConnection&&a.nextConnection.targetBlock()}this.updateShape_();this.reconnectChildBlocks_(b,c,d)},saveConnections:function(a){a=a.nextConnection.targetBlock();for(var b=1;a;){switch(a.type){case "controls_if_elseif":var c=this.getInput("IF"+b),d=this.getInput("DO"+b);a.valueConnection_=c&&c.connection.targetConnection;
a.statementConnection_=d&&d.connection.targetConnection;b++;break;case "controls_if_else":d=this.getInput("ELSE");a.statementConnection_=d&&d.connection.targetConnection;break;default:throw TypeError("Unknown block type: "+a.type);}a=a.nextConnection&&a.nextConnection.targetBlock()}},rebuildShape_:function(){var a=[null],b=[null],c=null;this.getInput("ELSE")&&(c=this.getInput("ELSE").connection.targetConnection);for(var d=1;this.getInput("IF"+d);){var e=this.getInput("IF"+d),f=this.getInput("DO"+
d);a.push(e.connection.targetConnection);b.push(f.connection.targetConnection);d++}this.updateShape_();this.reconnectChildBlocks_(a,b,c)},updateShape_:function(){this.getInput("ELSE")&&this.removeInput("ELSE");for(var a=1;this.getInput("IF"+a);)this.removeInput("IF"+a),this.removeInput("DO"+a),a++;for(a=1;a<=this.elseifCount_;a++)this.appendValueInput("IF"+a).setCheck("Boolean").appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSEIF),this.appendStatementInput("DO"+a).appendField(Blockly.Msg.CONTROLS_IF_MSG_THEN);
this.elseCount_&&this.appendStatementInput("ELSE").appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSE)},reconnectChildBlocks_:function(a,b,c){for(var d=1;d<=this.elseifCount_;d++)Blockly.Mutator.reconnect(a[d],this,"IF"+d),Blockly.Mutator.reconnect(b[d],this,"DO"+d);Blockly.Mutator.reconnect(c,this,"ELSE")}};Blockly.Extensions.registerMutator("controls_if_mutator",Blockly.Constants.Logic.CONTROLS_IF_MUTATOR_MIXIN,null,["controls_if_elseif","controls_if_else"]);
Blockly.Constants.Logic.CONTROLS_IF_TOOLTIP_EXTENSION=function(){this.setTooltip(function(){if(this.elseifCount_||this.elseCount_){if(!this.elseifCount_&&this.elseCount_)return Blockly.Msg.CONTROLS_IF_TOOLTIP_2;if(this.elseifCount_&&!this.elseCount_)return Blockly.Msg.CONTROLS_IF_TOOLTIP_3;if(this.elseifCount_&&this.elseCount_)return Blockly.Msg.CONTROLS_IF_TOOLTIP_4}else return Blockly.Msg.CONTROLS_IF_TOOLTIP_1;return""}.bind(this))};Blockly.Extensions.register("controls_if_tooltip",Blockly.Constants.Logic.CONTROLS_IF_TOOLTIP_EXTENSION);
Blockly.Constants.Logic.LOGIC_COMPARE_ONCHANGE_MIXIN={onchange:function(a){this.prevBlocks_||(this.prevBlocks_=[null,null]);var b=this.getInputTargetBlock("A"),c=this.getInputTargetBlock("B");b&&c&&!b.outputConnection.checkType(c.outputConnection)&&(Blockly.Events.setGroup(a.group),a=this.prevBlocks_[0],a!==b&&(b.unplug(),!a||a.isDisposed()||a.isShadow()||this.getInput("A").connection.connect(a.outputConnection)),b=this.prevBlocks_[1],b!==c&&(c.unplug(),!b||b.isDisposed()||b.isShadow()||this.getInput("B").connection.connect(b.outputConnection)),
this.bumpNeighbours(),Blockly.Events.setGroup(!1));this.prevBlocks_[0]=this.getInputTargetBlock("A");this.prevBlocks_[1]=this.getInputTargetBlock("B")}};Blockly.Constants.Logic.LOGIC_COMPARE_EXTENSION=function(){this.mixin(Blockly.Constants.Logic.LOGIC_COMPARE_ONCHANGE_MIXIN)};Blockly.Extensions.register("logic_compare",Blockly.Constants.Logic.LOGIC_COMPARE_EXTENSION);
Blockly.Constants.Logic.LOGIC_TERNARY_ONCHANGE_MIXIN={prevParentConnection_:null,onchange:function(a){var b=this.getInputTargetBlock("THEN"),c=this.getInputTargetBlock("ELSE"),d=this.outputConnection.targetConnection;if((b||c)&&d)for(var e=0;2>e;e++){var f=1==e?b:c;f&&!f.outputConnection.checkType(d)&&(Blockly.Events.setGroup(a.group),d===this.prevParentConnection_?(this.unplug(),d.getSourceBlock().bumpNeighbours()):(f.unplug(),f.bumpNeighbours()),Blockly.Events.setGroup(!1))}this.prevParentConnection_=
d}};Blockly.Extensions.registerMixin("logic_ternary",Blockly.Constants.Logic.LOGIC_TERNARY_ONCHANGE_MIXIN);Blockly.Blocks.loops={};Blockly.Constants.Loops={};Blockly.Constants.Loops.HUE=120;
Blockly.defineBlocksWithJsonArray([{type:"controls_repeat_ext",message0:"%{BKY_CONTROLS_REPEAT_TITLE}",args0:[{type:"input_value",name:"TIMES",check:"Number"}],message1:"%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",args1:[{type:"input_statement",name:"DO"}],previousStatement:null,nextStatement:null,style:"loop_blocks",tooltip:"%{BKY_CONTROLS_REPEAT_TOOLTIP}",helpUrl:"%{BKY_CONTROLS_REPEAT_HELPURL}"},{type:"controls_repeat",message0:"%{BKY_CONTROLS_REPEAT_TITLE}",args0:[{type:"field_number",name:"TIMES",value:10,
min:0,precision:1}],message1:"%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",args1:[{type:"input_statement",name:"DO"}],previousStatement:null,nextStatement:null,style:"loop_blocks",tooltip:"%{BKY_CONTROLS_REPEAT_TOOLTIP}",helpUrl:"%{BKY_CONTROLS_REPEAT_HELPURL}"},{type:"controls_whileUntil",message0:"%1 %2",args0:[{type:"field_dropdown",name:"MODE",options:[["%{BKY_CONTROLS_WHILEUNTIL_OPERATOR_WHILE}","WHILE"],["%{BKY_CONTROLS_WHILEUNTIL_OPERATOR_UNTIL}","UNTIL"]]},{type:"input_value",name:"BOOL",check:"Boolean"}],
message1:"%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",args1:[{type:"input_statement",name:"DO"}],previousStatement:null,nextStatement:null,style:"loop_blocks",helpUrl:"%{BKY_CONTROLS_WHILEUNTIL_HELPURL}",extensions:["controls_whileUntil_tooltip"]},{type:"controls_for",message0:"%{BKY_CONTROLS_FOR_TITLE}",args0:[{type:"field_variable",name:"VAR",variable:null},{type:"input_value",name:"FROM",check:"Number",align:"RIGHT"},{type:"input_value",name:"TO",check:"Number",align:"RIGHT"},{type:"input_value",name:"BY",
check:"Number",align:"RIGHT"}],message1:"%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",args1:[{type:"input_statement",name:"DO"}],inputsInline:!0,previousStatement:null,nextStatement:null,style:"loop_blocks",helpUrl:"%{BKY_CONTROLS_FOR_HELPURL}",extensions:["contextMenu_newGetVariableBlock","controls_for_tooltip"]},{type:"controls_forEach",message0:"%{BKY_CONTROLS_FOREACH_TITLE}",args0:[{type:"field_variable",name:"VAR",variable:null},{type:"input_value",name:"LIST",check:"Array"}],message1:"%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",
args1:[{type:"input_statement",name:"DO"}],previousStatement:null,nextStatement:null,style:"loop_blocks",helpUrl:"%{BKY_CONTROLS_FOREACH_HELPURL}",extensions:["contextMenu_newGetVariableBlock","controls_forEach_tooltip"]},{type:"controls_flow_statements",message0:"%1",args0:[{type:"field_dropdown",name:"FLOW",options:[["%{BKY_CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK}","BREAK"],["%{BKY_CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE}","CONTINUE"]]}],previousStatement:null,style:"loop_blocks",helpUrl:"%{BKY_CONTROLS_FLOW_STATEMENTS_HELPURL}",
extensions:["controls_flow_tooltip","controls_flow_in_loop_check"]}]);Blockly.Constants.Loops.WHILE_UNTIL_TOOLTIPS={WHILE:"%{BKY_CONTROLS_WHILEUNTIL_TOOLTIP_WHILE}",UNTIL:"%{BKY_CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL}"};Blockly.Extensions.register("controls_whileUntil_tooltip",Blockly.Extensions.buildTooltipForDropdown("MODE",Blockly.Constants.Loops.WHILE_UNTIL_TOOLTIPS));Blockly.Constants.Loops.BREAK_CONTINUE_TOOLTIPS={BREAK:"%{BKY_CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK}",CONTINUE:"%{BKY_CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE}"};
Blockly.Extensions.register("controls_flow_tooltip",Blockly.Extensions.buildTooltipForDropdown("FLOW",Blockly.Constants.Loops.BREAK_CONTINUE_TOOLTIPS));
Blockly.Constants.Loops.CUSTOM_CONTEXT_MENU_CREATE_VARIABLES_GET_MIXIN={customContextMenu:function(a){if(!this.isInFlyout){var b=this.getField("VAR").getVariable(),c=b.name;if(!this.isCollapsed()&&null!=c){var d={enabled:!0};d.text=Blockly.Msg.VARIABLES_SET_CREATE_GET.replace("%1",c);b=Blockly.Variables.generateVariableFieldDom(b);c=Blockly.utils.xml.createElement("block");c.setAttribute("type","variables_get");c.appendChild(b);d.callback=Blockly.ContextMenu.callbackFactory(this,c);a.push(d)}}}};
Blockly.Extensions.registerMixin("contextMenu_newGetVariableBlock",Blockly.Constants.Loops.CUSTOM_CONTEXT_MENU_CREATE_VARIABLES_GET_MIXIN);Blockly.Extensions.register("controls_for_tooltip",Blockly.Extensions.buildTooltipWithFieldText("%{BKY_CONTROLS_FOR_TOOLTIP}","VAR"));Blockly.Extensions.register("controls_forEach_tooltip",Blockly.Extensions.buildTooltipWithFieldText("%{BKY_CONTROLS_FOREACH_TOOLTIP}","VAR"));
Blockly.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN={LOOP_TYPES:["controls_repeat","controls_repeat_ext","controls_forEach","controls_for","controls_whileUntil"],suppressPrefixSuffix:!0,getSurroundLoop:function(a){do{if(-1!=Blockly.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN.LOOP_TYPES.indexOf(a.type))return a;a=a.getSurroundParent()}while(a);return null},onchange:function(a){if(this.workspace.isDragging&&!this.workspace.isDragging()&&a.type==Blockly.Events.BLOCK_MOVE&&a.blockId==this.id){var b=
Blockly.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN.getSurroundLoop(this);this.setWarningText(b?null:Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING);if(!this.isInFlyout){var c=Blockly.Events.getGroup();Blockly.Events.setGroup(a.group);this.setEnabled(b);Blockly.Events.setGroup(c)}}}};Blockly.Extensions.registerMixin("controls_flow_in_loop_check",Blockly.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN);Blockly.Blocks.math={};Blockly.Constants.Math={};Blockly.Constants.Math.HUE=230;
Blockly.defineBlocksWithJsonArray([{type:"math_number",message0:"%1",args0:[{type:"field_number",name:"NUM",value:0}],output:"Number",helpUrl:"%{BKY_MATH_NUMBER_HELPURL}",style:"math_blocks",tooltip:"%{BKY_MATH_NUMBER_TOOLTIP}",extensions:["parent_tooltip_when_inline"]},{type:"math_arithmetic",message0:"%1 %2 %3",args0:[{type:"input_value",name:"A",check:"Number"},{type:"field_dropdown",name:"OP",options:[["%{BKY_MATH_ADDITION_SYMBOL}","ADD"],["%{BKY_MATH_SUBTRACTION_SYMBOL}","MINUS"],["%{BKY_MATH_MULTIPLICATION_SYMBOL}",
"MULTIPLY"],["%{BKY_MATH_DIVISION_SYMBOL}","DIVIDE"],["%{BKY_MATH_POWER_SYMBOL}","POWER"]]},{type:"input_value",name:"B",check:"Number"}],inputsInline:!0,output:"Number",style:"math_blocks",helpUrl:"%{BKY_MATH_ARITHMETIC_HELPURL}",extensions:["math_op_tooltip"]},{type:"math_single",message0:"%1 %2",args0:[{type:"field_dropdown",name:"OP",options:[["%{BKY_MATH_SINGLE_OP_ROOT}","ROOT"],["%{BKY_MATH_SINGLE_OP_ABSOLUTE}","ABS"],["-","NEG"],["ln","LN"],["log10","LOG10"],["e^","EXP"],["10^","POW10"]]},
{type:"input_value",name:"NUM",check:"Number"}],output:"Number",style:"math_blocks",helpUrl:"%{BKY_MATH_SINGLE_HELPURL}",extensions:["math_op_tooltip"]},{type:"math_trig",message0:"%1 %2",args0:[{type:"field_dropdown",name:"OP",options:[["%{BKY_MATH_TRIG_SIN}","SIN"],["%{BKY_MATH_TRIG_COS}","COS"],["%{BKY_MATH_TRIG_TAN}","TAN"],["%{BKY_MATH_TRIG_ASIN}","ASIN"],["%{BKY_MATH_TRIG_ACOS}","ACOS"],["%{BKY_MATH_TRIG_ATAN}","ATAN"]]},{type:"input_value",name:"NUM",check:"Number"}],output:"Number",style:"math_blocks",
helpUrl:"%{BKY_MATH_TRIG_HELPURL}",extensions:["math_op_tooltip"]},{type:"math_constant",message0:"%1",args0:[{type:"field_dropdown",name:"CONSTANT",options:[["\u03c0","PI"],["e","E"],["\u03c6","GOLDEN_RATIO"],["sqrt(2)","SQRT2"],["sqrt(\u00bd)","SQRT1_2"],["\u221e","INFINITY"]]}],output:"Number",style:"math_blocks",tooltip:"%{BKY_MATH_CONSTANT_TOOLTIP}",helpUrl:"%{BKY_MATH_CONSTANT_HELPURL}"},{type:"math_number_property",message0:"%1 %2",args0:[{type:"input_value",name:"NUMBER_TO_CHECK",check:"Number"},
{type:"field_dropdown",name:"PROPERTY",options:[["%{BKY_MATH_IS_EVEN}","EVEN"],["%{BKY_MATH_IS_ODD}","ODD"],["%{BKY_MATH_IS_PRIME}","PRIME"],["%{BKY_MATH_IS_WHOLE}","WHOLE"],["%{BKY_MATH_IS_POSITIVE}","POSITIVE"],["%{BKY_MATH_IS_NEGATIVE}","NEGATIVE"],["%{BKY_MATH_IS_DIVISIBLE_BY}","DIVISIBLE_BY"]]}],inputsInline:!0,output:"Boolean",style:"math_blocks",tooltip:"%{BKY_MATH_IS_TOOLTIP}",mutator:"math_is_divisibleby_mutator"},{type:"math_change",message0:"%{BKY_MATH_CHANGE_TITLE}",args0:[{type:"field_variable",
name:"VAR",variable:"%{BKY_MATH_CHANGE_TITLE_ITEM}"},{type:"input_value",name:"DELTA",check:"Number"}],previousStatement:null,nextStatement:null,style:"variable_blocks",helpUrl:"%{BKY_MATH_CHANGE_HELPURL}",extensions:["math_change_tooltip"]},{type:"math_round",message0:"%1 %2",args0:[{type:"field_dropdown",name:"OP",options:[["%{BKY_MATH_ROUND_OPERATOR_ROUND}","ROUND"],["%{BKY_MATH_ROUND_OPERATOR_ROUNDUP}","ROUNDUP"],["%{BKY_MATH_ROUND_OPERATOR_ROUNDDOWN}","ROUNDDOWN"]]},{type:"input_value",name:"NUM",
check:"Number"}],output:"Number",style:"math_blocks",helpUrl:"%{BKY_MATH_ROUND_HELPURL}",tooltip:"%{BKY_MATH_ROUND_TOOLTIP}"},{type:"math_on_list",message0:"%1 %2",args0:[{type:"field_dropdown",name:"OP",options:[["%{BKY_MATH_ONLIST_OPERATOR_SUM}","SUM"],["%{BKY_MATH_ONLIST_OPERATOR_MIN}","MIN"],["%{BKY_MATH_ONLIST_OPERATOR_MAX}","MAX"],["%{BKY_MATH_ONLIST_OPERATOR_AVERAGE}","AVERAGE"],["%{BKY_MATH_ONLIST_OPERATOR_MEDIAN}","MEDIAN"],["%{BKY_MATH_ONLIST_OPERATOR_MODE}","MODE"],["%{BKY_MATH_ONLIST_OPERATOR_STD_DEV}",
"STD_DEV"],["%{BKY_MATH_ONLIST_OPERATOR_RANDOM}","RANDOM"]]},{type:"input_value",name:"LIST",check:"Array"}],output:"Number",style:"math_blocks",helpUrl:"%{BKY_MATH_ONLIST_HELPURL}",mutator:"math_modes_of_list_mutator",extensions:["math_op_tooltip"]},{type:"math_modulo",message0:"%{BKY_MATH_MODULO_TITLE}",args0:[{type:"input_value",name:"DIVIDEND",check:"Number"},{type:"input_value",name:"DIVISOR",check:"Number"}],inputsInline:!0,output:"Number",style:"math_blocks",tooltip:"%{BKY_MATH_MODULO_TOOLTIP}",
helpUrl:"%{BKY_MATH_MODULO_HELPURL}"},{type:"math_constrain",message0:"%{BKY_MATH_CONSTRAIN_TITLE}",args0:[{type:"input_value",name:"VALUE",check:"Number"},{type:"input_value",name:"LOW",check:"Number"},{type:"input_value",name:"HIGH",check:"Number"}],inputsInline:!0,output:"Number",style:"math_blocks",tooltip:"%{BKY_MATH_CONSTRAIN_TOOLTIP}",helpUrl:"%{BKY_MATH_CONSTRAIN_HELPURL}"},{type:"math_random_int",message0:"%{BKY_MATH_RANDOM_INT_TITLE}",args0:[{type:"input_value",name:"FROM",check:"Number"},
{type:"input_value",name:"TO",check:"Number"}],inputsInline:!0,output:"Number",style:"math_blocks",tooltip:"%{BKY_MATH_RANDOM_INT_TOOLTIP}",helpUrl:"%{BKY_MATH_RANDOM_INT_HELPURL}"},{type:"math_random_float",message0:"%{BKY_MATH_RANDOM_FLOAT_TITLE_RANDOM}",output:"Number",style:"math_blocks",tooltip:"%{BKY_MATH_RANDOM_FLOAT_TOOLTIP}",helpUrl:"%{BKY_MATH_RANDOM_FLOAT_HELPURL}"},{type:"math_atan2",message0:"%{BKY_MATH_ATAN2_TITLE}",args0:[{type:"input_value",name:"X",check:"Number"},{type:"input_value",
name:"Y",check:"Number"}],inputsInline:!0,output:"Number",style:"math_blocks",tooltip:"%{BKY_MATH_ATAN2_TOOLTIP}",helpUrl:"%{BKY_MATH_ATAN2_HELPURL}"}]);
Blockly.Constants.Math.TOOLTIPS_BY_OP={ADD:"%{BKY_MATH_ARITHMETIC_TOOLTIP_ADD}",MINUS:"%{BKY_MATH_ARITHMETIC_TOOLTIP_MINUS}",MULTIPLY:"%{BKY_MATH_ARITHMETIC_TOOLTIP_MULTIPLY}",DIVIDE:"%{BKY_MATH_ARITHMETIC_TOOLTIP_DIVIDE}",POWER:"%{BKY_MATH_ARITHMETIC_TOOLTIP_POWER}",ROOT:"%{BKY_MATH_SINGLE_TOOLTIP_ROOT}",ABS:"%{BKY_MATH_SINGLE_TOOLTIP_ABS}",NEG:"%{BKY_MATH_SINGLE_TOOLTIP_NEG}",LN:"%{BKY_MATH_SINGLE_TOOLTIP_LN}",LOG10:"%{BKY_MATH_SINGLE_TOOLTIP_LOG10}",EXP:"%{BKY_MATH_SINGLE_TOOLTIP_EXP}",POW10:"%{BKY_MATH_SINGLE_TOOLTIP_POW10}",
SIN:"%{BKY_MATH_TRIG_TOOLTIP_SIN}",COS:"%{BKY_MATH_TRIG_TOOLTIP_COS}",TAN:"%{BKY_MATH_TRIG_TOOLTIP_TAN}",ASIN:"%{BKY_MATH_TRIG_TOOLTIP_ASIN}",ACOS:"%{BKY_MATH_TRIG_TOOLTIP_ACOS}",ATAN:"%{BKY_MATH_TRIG_TOOLTIP_ATAN}",SUM:"%{BKY_MATH_ONLIST_TOOLTIP_SUM}",MIN:"%{BKY_MATH_ONLIST_TOOLTIP_MIN}",MAX:"%{BKY_MATH_ONLIST_TOOLTIP_MAX}",AVERAGE:"%{BKY_MATH_ONLIST_TOOLTIP_AVERAGE}",MEDIAN:"%{BKY_MATH_ONLIST_TOOLTIP_MEDIAN}",MODE:"%{BKY_MATH_ONLIST_TOOLTIP_MODE}",STD_DEV:"%{BKY_MATH_ONLIST_TOOLTIP_STD_DEV}",RANDOM:"%{BKY_MATH_ONLIST_TOOLTIP_RANDOM}"};
Blockly.Extensions.register("math_op_tooltip",Blockly.Extensions.buildTooltipForDropdown("OP",Blockly.Constants.Math.TOOLTIPS_BY_OP));
Blockly.Constants.Math.IS_DIVISIBLEBY_MUTATOR_MIXIN={mutationToDom:function(){var a=Blockly.utils.xml.createElement("mutation"),b="DIVISIBLE_BY"==this.getFieldValue("PROPERTY");a.setAttribute("divisor_input",b);return a},domToMutation:function(a){a="true"==a.getAttribute("divisor_input");this.updateShape_(a)},updateShape_:function(a){var b=this.getInput("DIVISOR");a?b||this.appendValueInput("DIVISOR").setCheck("Number"):b&&this.removeInput("DIVISOR")}};
Blockly.Constants.Math.IS_DIVISIBLE_MUTATOR_EXTENSION=function(){this.getField("PROPERTY").setValidator(function(a){a="DIVISIBLE_BY"==a;this.getSourceBlock().updateShape_(a)})};Blockly.Extensions.registerMutator("math_is_divisibleby_mutator",Blockly.Constants.Math.IS_DIVISIBLEBY_MUTATOR_MIXIN,Blockly.Constants.Math.IS_DIVISIBLE_MUTATOR_EXTENSION);Blockly.Extensions.register("math_change_tooltip",Blockly.Extensions.buildTooltipWithFieldText("%{BKY_MATH_CHANGE_TOOLTIP}","VAR"));
Blockly.Constants.Math.LIST_MODES_MUTATOR_MIXIN={updateType_:function(a){"MODE"==a?this.outputConnection.setCheck("Array"):this.outputConnection.setCheck("Number")},mutationToDom:function(){var a=Blockly.utils.xml.createElement("mutation");a.setAttribute("op",this.getFieldValue("OP"));return a},domToMutation:function(a){this.updateType_(a.getAttribute("op"))}};Blockly.Constants.Math.LIST_MODES_MUTATOR_EXTENSION=function(){this.getField("OP").setValidator(function(a){this.updateType_(a)}.bind(this))};
Blockly.Extensions.registerMutator("math_modes_of_list_mutator",Blockly.Constants.Math.LIST_MODES_MUTATOR_MIXIN,Blockly.Constants.Math.LIST_MODES_MUTATOR_EXTENSION);Blockly.Blocks.procedures={};
Blockly.Blocks.procedures_defnoreturn={init:function(){var a=new Blockly.FieldTextInput("",Blockly.Procedures.rename);a.setSpellcheck(!1);this.appendDummyInput().appendField(Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE).appendField(a,"NAME").appendField("","PARAMS");this.setMutator(new Blockly.Mutator(["procedures_mutatorarg"]));(this.workspace.options.comments||this.workspace.options.parentWorkspace&&this.workspace.options.parentWorkspace.options.comments)&&Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT&&this.setCommentText(Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT);
this.setStyle("procedure_blocks");this.setTooltip(Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP);this.setHelpUrl(Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL);this.arguments_=[];this.argumentVarModels_=[];this.setStatements_(!0);this.statementConnection_=null},setStatements_:function(a){this.hasStatements_!==a&&(a?(this.appendStatementInput("STACK").appendField(Blockly.Msg.PROCEDURES_DEFNORETURN_DO),this.getInput("RETURN")&&this.moveInputBefore("STACK","RETURN")):this.removeInput("STACK",!0),this.hasStatements_=
a)},updateParams_:function(){var a="";this.arguments_.length&&(a=Blockly.Msg.PROCEDURES_BEFORE_PARAMS+" "+this.arguments_.join(", "));Blockly.Events.disable();try{this.setFieldValue(a,"PARAMS")}finally{Blockly.Events.enable()}},mutationToDom:function(a){var b=Blockly.utils.xml.createElement("mutation");a&&b.setAttribute("name",this.getFieldValue("NAME"));for(var c=0;c<this.argumentVarModels_.length;c++){var d=Blockly.utils.xml.createElement("arg"),e=this.argumentVarModels_[c];d.setAttribute("name",
e.name);d.setAttribute("varid",e.getId());a&&this.paramIds_&&d.setAttribute("paramId",this.paramIds_[c]);b.appendChild(d)}this.hasStatements_||b.setAttribute("statements","false");return b},domToMutation:function(a){this.arguments_=[];this.argumentVarModels_=[];for(var b=0,c;c=a.childNodes[b];b++)if("arg"==c.nodeName.toLowerCase()){var d=c.getAttribute("name");c=c.getAttribute("varid")||c.getAttribute("varId");this.arguments_.push(d);c=Blockly.Variables.getOrCreateVariablePackage(this.workspace,c,
d,"");null!=c?this.argumentVarModels_.push(c):console.log("Failed to create a variable with name "+d+", ignoring.")}this.updateParams_();Blockly.Procedures.mutateCallers(this);this.setStatements_("false"!==a.getAttribute("statements"))},decompose:function(a){var b=Blockly.utils.xml.createElement("block");b.setAttribute("type","procedures_mutatorcontainer");var c=Blockly.utils.xml.createElement("statement");c.setAttribute("name","STACK");b.appendChild(c);for(var d=0;d<this.arguments_.length;d++){var e=
Blockly.utils.xml.createElement("block");e.setAttribute("type","procedures_mutatorarg");var f=Blockly.utils.xml.createElement("field");f.setAttribute("name","NAME");var g=Blockly.utils.xml.createTextNode(this.arguments_[d]);f.appendChild(g);e.appendChild(f);f=Blockly.utils.xml.createElement("next");e.appendChild(f);c.appendChild(e);c=f}a=Blockly.Xml.domToBlock(b,a);"procedures_defreturn"==this.type?a.setFieldValue(this.hasStatements_,"STATEMENTS"):a.removeInput("STATEMENT_INPUT");Blockly.Procedures.mutateCallers(this);
return a},compose:function(a){this.arguments_=[];this.paramIds_=[];this.argumentVarModels_=[];for(var b=a.getInputTargetBlock("STACK");b;){var c=b.getFieldValue("NAME");this.arguments_.push(c);c=this.workspace.getVariable(c,"");this.argumentVarModels_.push(c);this.paramIds_.push(b.id);b=b.nextConnection&&b.nextConnection.targetBlock()}this.updateParams_();Blockly.Procedures.mutateCallers(this);a=a.getFieldValue("STATEMENTS");if(null!==a&&(a="TRUE"==a,this.hasStatements_!=a))if(a)this.setStatements_(!0),
Blockly.Mutator.reconnect(this.statementConnection_,this,"STACK"),this.statementConnection_=null;else{a=this.getInput("STACK").connection;if(this.statementConnection_=a.targetConnection)a=a.targetBlock(),a.unplug(),a.bumpNeighbours();this.setStatements_(!1)}},getProcedureDef:function(){return[this.getFieldValue("NAME"),this.arguments_,!1]},getVars:function(){return this.arguments_},getVarModels:function(){return this.argumentVarModels_},renameVarById:function(a,b){var c=this.workspace.getVariableById(a);
if(""==c.type){c=c.name;b=this.workspace.getVariableById(b);for(var d=!1,e=0;e<this.argumentVarModels_.length;e++)this.argumentVarModels_[e].getId()==a&&(this.arguments_[e]=b.name,this.argumentVarModels_[e]=b,d=!0);d&&(this.displayRenamedVar_(c,b.name),Blockly.Procedures.mutateCallers(this))}},updateVarName:function(a){for(var b=a.name,c=!1,d=0;d<this.argumentVarModels_.length;d++)if(this.argumentVarModels_[d].getId()==a.getId()){var e=this.arguments_[d];this.arguments_[d]=b;c=!0}c&&(this.displayRenamedVar_(e,
b),Blockly.Procedures.mutateCallers(this))},displayRenamedVar_:function(a,b){this.updateParams_();if(this.mutator&&this.mutator.isVisible())for(var c=this.mutator.workspace_.getAllBlocks(!1),d=0,e;e=c[d];d++)"procedures_mutatorarg"==e.type&&Blockly.Names.equals(a,e.getFieldValue("NAME"))&&e.setFieldValue(b,"NAME")},customContextMenu:function(a){if(!this.isInFlyout){var b={enabled:!0},c=this.getFieldValue("NAME");b.text=Blockly.Msg.PROCEDURES_CREATE_DO.replace("%1",c);var d=Blockly.utils.xml.createElement("mutation");
d.setAttribute("name",c);for(c=0;c<this.arguments_.length;c++){var e=Blockly.utils.xml.createElement("arg");e.setAttribute("name",this.arguments_[c]);d.appendChild(e)}c=Blockly.utils.xml.createElement("block");c.setAttribute("type",this.callType_);c.appendChild(d);b.callback=Blockly.ContextMenu.callbackFactory(this,c);a.push(b);if(!this.isCollapsed())for(c=0;c<this.argumentVarModels_.length;c++)b={enabled:!0},d=this.argumentVarModels_[c],b.text=Blockly.Msg.VARIABLES_SET_CREATE_GET.replace("%1",d.name),
d=Blockly.Variables.generateVariableFieldDom(d),e=Blockly.utils.xml.createElement("block"),e.setAttribute("type","variables_get"),e.appendChild(d),b.callback=Blockly.ContextMenu.callbackFactory(this,e),a.push(b)}},callType_:"procedures_callnoreturn"};
Blockly.Blocks.procedures_defreturn={init:function(){var a=new Blockly.FieldTextInput("",Blockly.Procedures.rename);a.setSpellcheck(!1);this.appendDummyInput().appendField(Blockly.Msg.PROCEDURES_DEFRETURN_TITLE).appendField(a,"NAME").appendField("","PARAMS");this.appendValueInput("RETURN").setAlign(Blockly.ALIGN_RIGHT).appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);this.setMutator(new Blockly.Mutator(["procedures_mutatorarg"]));(this.workspace.options.comments||this.workspace.options.parentWorkspace&&
this.workspace.options.parentWorkspace.options.comments)&&Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT&&this.setCommentText(Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT);this.setStyle("procedure_blocks");this.setTooltip(Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP);this.setHelpUrl(Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL);this.arguments_=[];this.argumentVarModels_=[];this.setStatements_(!0);this.statementConnection_=null},setStatements_:Blockly.Blocks.procedures_defnoreturn.setStatements_,updateParams_:Blockly.Blocks.procedures_defnoreturn.updateParams_,
mutationToDom:Blockly.Blocks.procedures_defnoreturn.mutationToDom,domToMutation:Blockly.Blocks.procedures_defnoreturn.domToMutation,decompose:Blockly.Blocks.procedures_defnoreturn.decompose,compose:Blockly.Blocks.procedures_defnoreturn.compose,getProcedureDef:function(){return[this.getFieldValue("NAME"),this.arguments_,!0]},getVars:Blockly.Blocks.procedures_defnoreturn.getVars,getVarModels:Blockly.Blocks.procedures_defnoreturn.getVarModels,renameVarById:Blockly.Blocks.procedures_defnoreturn.renameVarById,
updateVarName:Blockly.Blocks.procedures_defnoreturn.updateVarName,displayRenamedVar_:Blockly.Blocks.procedures_defnoreturn.displayRenamedVar_,customContextMenu:Blockly.Blocks.procedures_defnoreturn.customContextMenu,callType_:"procedures_callreturn"};
Blockly.Blocks.procedures_mutatorcontainer={init:function(){this.appendDummyInput().appendField(Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE);this.appendStatementInput("STACK");this.appendDummyInput("STATEMENT_INPUT").appendField(Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS).appendField(new Blockly.FieldCheckbox("TRUE"),"STATEMENTS");this.setStyle("procedure_blocks");this.setTooltip(Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP);this.contextMenu=!1}};
Blockly.Blocks.procedures_mutatorarg={init:function(){var a=new Blockly.FieldTextInput(Blockly.Procedures.DEFAULT_ARG,this.validator_);a.oldShowEditorFn_=a.showEditor_;a.showEditor_=function(){this.createdVariables_=[];this.oldShowEditorFn_()};this.appendDummyInput().appendField(Blockly.Msg.PROCEDURES_MUTATORARG_TITLE).appendField(a,"NAME");this.setPreviousStatement(!0);this.setNextStatement(!0);this.setStyle("procedure_blocks");this.setTooltip(Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP);this.contextMenu=
!1;a.onFinishEditing_=this.deleteIntermediateVars_;a.createdVariables_=[];a.onFinishEditing_("x")},validator_:function(a){var b=this.getSourceBlock(),c=Blockly.Mutator.findParentWs(b.workspace);a=a.replace(/[\s\xa0]+/g," ").replace(/^ | $/g,"");if(!a)return null;for(var d=(b.workspace.targetWorkspace||b.workspace).getAllBlocks(!1),e=a.toLowerCase(),f=0;f<d.length;f++)if(d[f].id!=this.getSourceBlock().id){var g=d[f].getFieldValue("NAME");if(g&&g.toLowerCase()==e)return null}if(b.isInFlyout)return a;
(b=c.getVariable(a,""))&&b.name!=a&&c.renameVariableById(b.getId(),a);b||(b=c.createVariable(a,""))&&this.createdVariables_&&this.createdVariables_.push(b);return a},deleteIntermediateVars_:function(a){var b=Blockly.Mutator.findParentWs(this.getSourceBlock().workspace);if(b)for(var c=0;c<this.createdVariables_.length;c++){var d=this.createdVariables_[c];d.name!=a&&b.deleteVariableById(d.getId())}}};
Blockly.Blocks.procedures_callnoreturn={init:function(){this.appendDummyInput("TOPROW").appendField(this.id,"NAME");this.setPreviousStatement(!0);this.setNextStatement(!0);this.setStyle("procedure_blocks");this.setHelpUrl(Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL);this.arguments_=[];this.argumentVarModels_=[];this.quarkConnections_={};this.quarkIds_=null;this.previousEnabledState_=!0},getProcedureCall:function(){return this.getFieldValue("NAME")},renameProcedure:function(a,b){Blockly.Names.equals(a,
this.getProcedureCall())&&(this.setFieldValue(b,"NAME"),this.setTooltip((this.outputConnection?Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP:Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP).replace("%1",b)))},setProcedureParameters_:function(a,b){var c=Blockly.Procedures.getDefinition(this.getProcedureCall(),this.workspace),d=c&&c.mutator&&c.mutator.isVisible();d||(this.quarkConnections_={},this.quarkIds_=null);if(b)if(a.join("\n")==this.arguments_.join("\n"))this.quarkIds_=b;else{if(b.length!=a.length)throw RangeError("paramNames and paramIds must be the same length.");
this.setCollapsed(!1);this.quarkIds_||(this.quarkConnections_={},this.quarkIds_=[]);c=this.rendered;this.rendered=!1;for(var e=0;e<this.arguments_.length;e++){var f=this.getInput("ARG"+e);f&&(f=f.connection.targetConnection,this.quarkConnections_[this.quarkIds_[e]]=f,d&&f&&-1==b.indexOf(this.quarkIds_[e])&&(f.disconnect(),f.getSourceBlock().bumpNeighbours()))}this.arguments_=[].concat(a);this.argumentVarModels_=[];for(e=0;e<this.arguments_.length;e++)a=Blockly.Variables.getOrCreateVariablePackage(this.workspace,
null,this.arguments_[e],""),this.argumentVarModels_.push(a);this.updateShape_();if(this.quarkIds_=b)for(e=0;e<this.arguments_.length;e++)b=this.quarkIds_[e],b in this.quarkConnections_&&(f=this.quarkConnections_[b],Blockly.Mutator.reconnect(f,this,"ARG"+e)||delete this.quarkConnections_[b]);(this.rendered=c)&&this.render()}},updateShape_:function(){for(var a=0;a<this.arguments_.length;a++){var b=this.getField("ARGNAME"+a);if(b){Blockly.Events.disable();try{b.setValue(this.arguments_[a])}finally{Blockly.Events.enable()}}else b=
new Blockly.FieldLabel(this.arguments_[a]),this.appendValueInput("ARG"+a).setAlign(Blockly.ALIGN_RIGHT).appendField(b,"ARGNAME"+a).init()}for(;this.getInput("ARG"+a);)this.removeInput("ARG"+a),a++;if(a=this.getInput("TOPROW"))this.arguments_.length?this.getField("WITH")||(a.appendField(Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS,"WITH"),a.init()):this.getField("WITH")&&a.removeField("WITH")},mutationToDom:function(){var a=Blockly.utils.xml.createElement("mutation");a.setAttribute("name",this.getProcedureCall());
for(var b=0;b<this.arguments_.length;b++){var c=Blockly.utils.xml.createElement("arg");c.setAttribute("name",this.arguments_[b]);a.appendChild(c)}return a},domToMutation:function(a){var b=a.getAttribute("name");this.renameProcedure(this.getProcedureCall(),b);b=[];for(var c=[],d=0,e;e=a.childNodes[d];d++)"arg"==e.nodeName.toLowerCase()&&(b.push(e.getAttribute("name")),c.push(e.getAttribute("paramId")));this.setProcedureParameters_(b,c)},getVarModels:function(){return this.argumentVarModels_},onchange:function(a){if(this.workspace&&
!this.workspace.isFlyout&&a.recordUndo)if(a.type==Blockly.Events.BLOCK_CREATE&&-1!=a.ids.indexOf(this.id)){var b=this.getProcedureCall();b=Blockly.Procedures.getDefinition(b,this.workspace);!b||b.type==this.defType_&&JSON.stringify(b.arguments_)==JSON.stringify(this.arguments_)||(b=null);if(!b){Blockly.Events.setGroup(a.group);a=Blockly.utils.xml.createElement("xml");b=Blockly.utils.xml.createElement("block");b.setAttribute("type",this.defType_);var c=this.getRelativeToSurfaceXY(),d=c.y+2*Blockly.SNAP_RADIUS;
b.setAttribute("x",c.x+Blockly.SNAP_RADIUS*(this.RTL?-1:1));b.setAttribute("y",d);c=this.mutationToDom();b.appendChild(c);c=Blockly.utils.xml.createElement("field");c.setAttribute("name","NAME");c.appendChild(Blockly.utils.xml.createTextNode(this.getProcedureCall()));b.appendChild(c);a.appendChild(b);Blockly.Xml.domToWorkspace(a,this.workspace);Blockly.Events.setGroup(!1)}}else a.type==Blockly.Events.BLOCK_DELETE?(b=this.getProcedureCall(),b=Blockly.Procedures.getDefinition(b,this.workspace),b||(Blockly.Events.setGroup(a.group),
this.dispose(!0),Blockly.Events.setGroup(!1))):a.type==Blockly.Events.CHANGE&&"disabled"==a.element&&(b=this.getProcedureCall(),(b=Blockly.Procedures.getDefinition(b,this.workspace))&&b.id==a.blockId&&((b=Blockly.Events.getGroup())&&console.log("Saw an existing group while responding to a definition change"),Blockly.Events.setGroup(a.group),a.newValue?(this.previousEnabledState_=this.isEnabled(),this.setEnabled(!1)):this.setEnabled(this.previousEnabledState_),Blockly.Events.setGroup(b)))},customContextMenu:function(a){if(this.workspace.isMovable()){var b=
{enabled:!0};b.text=Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF;var c=this.getProcedureCall(),d=this.workspace;b.callback=function(){var a=Blockly.Procedures.getDefinition(c,d);a&&(d.centerOnBlock(a.id),a.select())};a.push(b)}},defType_:"procedures_defnoreturn"};
Blockly.Blocks.procedures_callreturn={init:function(){this.appendDummyInput("TOPROW").appendField("","NAME");this.setOutput(!0);this.setStyle("procedure_blocks");this.setHelpUrl(Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL);this.arguments_=[];this.quarkConnections_={};this.quarkIds_=null;this.previousEnabledState_=!0},getProcedureCall:Blockly.Blocks.procedures_callnoreturn.getProcedureCall,renameProcedure:Blockly.Blocks.procedures_callnoreturn.renameProcedure,setProcedureParameters_:Blockly.Blocks.procedures_callnoreturn.setProcedureParameters_,
updateShape_:Blockly.Blocks.procedures_callnoreturn.updateShape_,mutationToDom:Blockly.Blocks.procedures_callnoreturn.mutationToDom,domToMutation:Blockly.Blocks.procedures_callnoreturn.domToMutation,getVarModels:Blockly.Blocks.procedures_callnoreturn.getVarModels,onchange:Blockly.Blocks.procedures_callnoreturn.onchange,customContextMenu:Blockly.Blocks.procedures_callnoreturn.customContextMenu,defType_:"procedures_defreturn"};
Blockly.Blocks.procedures_ifreturn={init:function(){this.appendValueInput("CONDITION").setCheck("Boolean").appendField(Blockly.Msg.CONTROLS_IF_MSG_IF);this.appendValueInput("VALUE").appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);this.setInputsInline(!0);this.setPreviousStatement(!0);this.setNextStatement(!0);this.setStyle("procedure_blocks");this.setTooltip(Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP);this.setHelpUrl(Blockly.Msg.PROCEDURES_IFRETURN_HELPURL);this.hasReturnValue_=!0},mutationToDom:function(){var a=
Blockly.utils.xml.createElement("mutation");a.setAttribute("value",Number(this.hasReturnValue_));return a},domToMutation:function(a){this.hasReturnValue_=1==a.getAttribute("value");this.hasReturnValue_||(this.removeInput("VALUE"),this.appendDummyInput("VALUE").appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN))},onchange:function(a){if(this.workspace.isDragging&&!this.workspace.isDragging()){a=!1;var b=this;do{if(-1!=this.FUNCTION_TYPES.indexOf(b.type)){a=!0;break}b=b.getSurroundParent()}while(b);
a?("procedures_defnoreturn"==b.type&&this.hasReturnValue_?(this.removeInput("VALUE"),this.appendDummyInput("VALUE").appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN),this.hasReturnValue_=!1):"procedures_defreturn"!=b.type||this.hasReturnValue_||(this.removeInput("VALUE"),this.appendValueInput("VALUE").appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN),this.hasReturnValue_=!0),this.setWarningText(null),this.isInFlyout||this.setEnabled(!0)):(this.setWarningText(Blockly.Msg.PROCEDURES_IFRETURN_WARNING),
this.isInFlyout||this.getInheritedDisabled()||this.setEnabled(!1))}},FUNCTION_TYPES:["procedures_defnoreturn","procedures_defreturn"]};Blockly.Blocks.texts={};Blockly.Constants.Text={};Blockly.Constants.Text.HUE=160;
Blockly.defineBlocksWithJsonArray([{type:"text",message0:"%1",args0:[{type:"field_input",name:"TEXT",text:""}],output:"String",style:"text_blocks",helpUrl:"%{BKY_TEXT_TEXT_HELPURL}",tooltip:"%{BKY_TEXT_TEXT_TOOLTIP}",extensions:["text_quotes","parent_tooltip_when_inline"]},{type:"text_multiline",message0:"%1 %2",args0:[{type:"field_image",src:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAARCAYAAADpPU2iAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAdhgAAHYYBXaITgQAAABh0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMS42/U4J6AAAAP1JREFUOE+Vks0KQUEYhjmRIja4ABtZ2dm5A3t3Ia6AUm7CylYuQRaUhZSlLZJiQbFAyRnPN33y01HOW08z8873zpwzM4F3GWOCruvGIE4/rLaV+Nq1hVGMBqzhqlxgCys4wJA65xnogMHsQ5lujnYHTejBBCK2mE4abjCgMGhNxHgDFWjDSG07kdfVa2pZMf4ZyMAdWmpZMfYOsLiDMYMjlMB+K613QISRhTnITnsYg5yUd0DETmEoMlkFOeIT/A58iyK5E18BuTBfgYXfwNJv4P9/oEBerLylOnRhygmGdPpTTBZAPkde61lbQe4moWUvYUZYLfUNftIY4zwA5X2Z9AYnQrEAAAAASUVORK5CYII=",width:12,
height:17,alt:"\u00b6"},{type:"field_multilinetext",name:"TEXT",text:""}],output:"String",style:"text_blocks",helpUrl:"%{BKY_TEXT_TEXT_HELPURL}",tooltip:"%{BKY_TEXT_TEXT_TOOLTIP}",extensions:["parent_tooltip_when_inline"]},{type:"text_join",message0:"",output:"String",style:"text_blocks",helpUrl:"%{BKY_TEXT_JOIN_HELPURL}",tooltip:"%{BKY_TEXT_JOIN_TOOLTIP}",mutator:"text_join_mutator"},{type:"text_create_join_container",message0:"%{BKY_TEXT_CREATE_JOIN_TITLE_JOIN} %1 %2",args0:[{type:"input_dummy"},
{type:"input_statement",name:"STACK"}],style:"text_blocks",tooltip:"%{BKY_TEXT_CREATE_JOIN_TOOLTIP}",enableContextMenu:!1},{type:"text_create_join_item",message0:"%{BKY_TEXT_CREATE_JOIN_ITEM_TITLE_ITEM}",previousStatement:null,nextStatement:null,style:"text_blocks",tooltip:"%{BKY_TEXT_CREATE_JOIN_ITEM_TOOLTIP}",enableContextMenu:!1},{type:"text_append",message0:"%{BKY_TEXT_APPEND_TITLE}",args0:[{type:"field_variable",name:"VAR",variable:"%{BKY_TEXT_APPEND_VARIABLE}"},{type:"input_value",name:"TEXT"}],
previousStatement:null,nextStatement:null,style:"text_blocks",extensions:["text_append_tooltip"]},{type:"text_length",message0:"%{BKY_TEXT_LENGTH_TITLE}",args0:[{type:"input_value",name:"VALUE",check:["String","Array"]}],output:"Number",style:"text_blocks",tooltip:"%{BKY_TEXT_LENGTH_TOOLTIP}",helpUrl:"%{BKY_TEXT_LENGTH_HELPURL}"},{type:"text_isEmpty",message0:"%{BKY_TEXT_ISEMPTY_TITLE}",args0:[{type:"input_value",name:"VALUE",check:["String","Array"]}],output:"Boolean",style:"text_blocks",tooltip:"%{BKY_TEXT_ISEMPTY_TOOLTIP}",
helpUrl:"%{BKY_TEXT_ISEMPTY_HELPURL}"},{type:"text_indexOf",message0:"%{BKY_TEXT_INDEXOF_TITLE}",args0:[{type:"input_value",name:"VALUE",check:"String"},{type:"field_dropdown",name:"END",options:[["%{BKY_TEXT_INDEXOF_OPERATOR_FIRST}","FIRST"],["%{BKY_TEXT_INDEXOF_OPERATOR_LAST}","LAST"]]},{type:"input_value",name:"FIND",check:"String"}],output:"Number",style:"text_blocks",helpUrl:"%{BKY_TEXT_INDEXOF_HELPURL}",inputsInline:!0,extensions:["text_indexOf_tooltip"]},{type:"text_charAt",message0:"%{BKY_TEXT_CHARAT_TITLE}",
args0:[{type:"input_value",name:"VALUE",check:"String"},{type:"field_dropdown",name:"WHERE",options:[["%{BKY_TEXT_CHARAT_FROM_START}","FROM_START"],["%{BKY_TEXT_CHARAT_FROM_END}","FROM_END"],["%{BKY_TEXT_CHARAT_FIRST}","FIRST"],["%{BKY_TEXT_CHARAT_LAST}","LAST"],["%{BKY_TEXT_CHARAT_RANDOM}","RANDOM"]]}],output:"String",style:"text_blocks",helpUrl:"%{BKY_TEXT_CHARAT_HELPURL}",inputsInline:!0,mutator:"text_charAt_mutator"}]);
Blockly.Blocks.text_getSubstring={init:function(){this.WHERE_OPTIONS_1=[[Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START,"FROM_START"],[Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END,"FROM_END"],[Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST,"FIRST"]];this.WHERE_OPTIONS_2=[[Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START,"FROM_START"],[Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END,"FROM_END"],[Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST,"LAST"]];this.setHelpUrl(Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL);this.setStyle("text_blocks");
this.appendValueInput("STRING").setCheck("String").appendField(Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT);this.appendDummyInput("AT1");this.appendDummyInput("AT2");Blockly.Msg.TEXT_GET_SUBSTRING_TAIL&&this.appendDummyInput("TAIL").appendField(Blockly.Msg.TEXT_GET_SUBSTRING_TAIL);this.setInputsInline(!0);this.setOutput(!0,"String");this.updateAt_(1,!0);this.updateAt_(2,!0);this.setTooltip(Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP)},mutationToDom:function(){var a=Blockly.utils.xml.createElement("mutation"),
b=this.getInput("AT1").type==Blockly.INPUT_VALUE;a.setAttribute("at1",b);b=this.getInput("AT2").type==Blockly.INPUT_VALUE;a.setAttribute("at2",b);return a},domToMutation:function(a){var b="true"==a.getAttribute("at1");a="true"==a.getAttribute("at2");this.updateAt_(1,b);this.updateAt_(2,a)},updateAt_:function(a,b){this.removeInput("AT"+a);this.removeInput("ORDINAL"+a,!0);b?(this.appendValueInput("AT"+a).setCheck("Number"),Blockly.Msg.ORDINAL_NUMBER_SUFFIX&&this.appendDummyInput("ORDINAL"+a).appendField(Blockly.Msg.ORDINAL_NUMBER_SUFFIX)):
this.appendDummyInput("AT"+a);2==a&&Blockly.Msg.TEXT_GET_SUBSTRING_TAIL&&(this.removeInput("TAIL",!0),this.appendDummyInput("TAIL").appendField(Blockly.Msg.TEXT_GET_SUBSTRING_TAIL));var c=new Blockly.FieldDropdown(this["WHERE_OPTIONS_"+a],function(c){var e="FROM_START"==c||"FROM_END"==c;if(e!=b){var d=this.getSourceBlock();d.updateAt_(a,e);d.setFieldValue(c,"WHERE"+a);return null}});this.getInput("AT"+a).appendField(c,"WHERE"+a);1==a&&(this.moveInputBefore("AT1","AT2"),this.getInput("ORDINAL1")&&
this.moveInputBefore("ORDINAL1","AT2"))}};Blockly.Blocks.text_changeCase={init:function(){var a=[[Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE,"UPPERCASE"],[Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE,"LOWERCASE"],[Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE,"TITLECASE"]];this.setHelpUrl(Blockly.Msg.TEXT_CHANGECASE_HELPURL);this.setStyle("text_blocks");this.appendValueInput("TEXT").setCheck("String").appendField(new Blockly.FieldDropdown(a),"CASE");this.setOutput(!0,"String");this.setTooltip(Blockly.Msg.TEXT_CHANGECASE_TOOLTIP)}};
Blockly.Blocks.text_trim={init:function(){var a=[[Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH,"BOTH"],[Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT,"LEFT"],[Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT,"RIGHT"]];this.setHelpUrl(Blockly.Msg.TEXT_TRIM_HELPURL);this.setStyle("text_blocks");this.appendValueInput("TEXT").setCheck("String").appendField(new Blockly.FieldDropdown(a),"MODE");this.setOutput(!0,"String");this.setTooltip(Blockly.Msg.TEXT_TRIM_TOOLTIP)}};
Blockly.Blocks.text_print={init:function(){this.jsonInit({message0:Blockly.Msg.TEXT_PRINT_TITLE,args0:[{type:"input_value",name:"TEXT"}],previousStatement:null,nextStatement:null,style:"text_blocks",tooltip:Blockly.Msg.TEXT_PRINT_TOOLTIP,helpUrl:Blockly.Msg.TEXT_PRINT_HELPURL})}};
Blockly.Blocks.text_prompt_ext={init:function(){var a=[[Blockly.Msg.TEXT_PROMPT_TYPE_TEXT,"TEXT"],[Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER,"NUMBER"]];this.setHelpUrl(Blockly.Msg.TEXT_PROMPT_HELPURL);this.setStyle("text_blocks");var b=this;a=new Blockly.FieldDropdown(a,function(a){b.updateType_(a)});this.appendValueInput("TEXT").appendField(a,"TYPE");this.setOutput(!0,"String");this.setTooltip(function(){return"TEXT"==b.getFieldValue("TYPE")?Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT:Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER})},
updateType_:function(a){this.outputConnection.setCheck("NUMBER"==a?"Number":"String")},mutationToDom:function(){var a=Blockly.utils.xml.createElement("mutation");a.setAttribute("type",this.getFieldValue("TYPE"));return a},domToMutation:function(a){this.updateType_(a.getAttribute("type"))}};
Blockly.Blocks.text_prompt={init:function(){this.mixin(Blockly.Constants.Text.QUOTE_IMAGE_MIXIN);var a=[[Blockly.Msg.TEXT_PROMPT_TYPE_TEXT,"TEXT"],[Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER,"NUMBER"]],b=this;this.setHelpUrl(Blockly.Msg.TEXT_PROMPT_HELPURL);this.setStyle("text_blocks");a=new Blockly.FieldDropdown(a,function(a){b.updateType_(a)});this.appendDummyInput().appendField(a,"TYPE").appendField(this.newQuote_(!0)).appendField(new Blockly.FieldTextInput(""),"TEXT").appendField(this.newQuote_(!1));
this.setOutput(!0,"String");this.setTooltip(function(){return"TEXT"==b.getFieldValue("TYPE")?Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT:Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER})},updateType_:Blockly.Blocks.text_prompt_ext.updateType_,mutationToDom:Blockly.Blocks.text_prompt_ext.mutationToDom,domToMutation:Blockly.Blocks.text_prompt_ext.domToMutation};
Blockly.Blocks.text_count={init:function(){this.jsonInit({message0:Blockly.Msg.TEXT_COUNT_MESSAGE0,args0:[{type:"input_value",name:"SUB",check:"String"},{type:"input_value",name:"TEXT",check:"String"}],output:"Number",inputsInline:!0,style:"text_blocks",tooltip:Blockly.Msg.TEXT_COUNT_TOOLTIP,helpUrl:Blockly.Msg.TEXT_COUNT_HELPURL})}};
Blockly.Blocks.text_replace={init:function(){this.jsonInit({message0:Blockly.Msg.TEXT_REPLACE_MESSAGE0,args0:[{type:"input_value",name:"FROM",check:"String"},{type:"input_value",name:"TO",check:"String"},{type:"input_value",name:"TEXT",check:"String"}],output:"String",inputsInline:!0,style:"text_blocks",tooltip:Blockly.Msg.TEXT_REPLACE_TOOLTIP,helpUrl:Blockly.Msg.TEXT_REPLACE_HELPURL})}};
Blockly.Blocks.text_reverse={init:function(){this.jsonInit({message0:Blockly.Msg.TEXT_REVERSE_MESSAGE0,args0:[{type:"input_value",name:"TEXT",check:"String"}],output:"String",inputsInline:!0,style:"text_blocks",tooltip:Blockly.Msg.TEXT_REVERSE_TOOLTIP,helpUrl:Blockly.Msg.TEXT_REVERSE_HELPURL})}};
Blockly.Constants.Text.QUOTE_IMAGE_MIXIN={QUOTE_IMAGE_LEFT_DATAURI:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAQAAAAqJXdxAAAAn0lEQVQI1z3OMa5BURSF4f/cQhAKjUQhuQmFNwGJEUi0RKN5rU7FHKhpjEH3TEMtkdBSCY1EIv8r7nFX9e29V7EBAOvu7RPjwmWGH/VuF8CyN9/OAdvqIXYLvtRaNjx9mMTDyo+NjAN1HNcl9ZQ5oQMM3dgDUqDo1l8DzvwmtZN7mnD+PkmLa+4mhrxVA9fRowBWmVBhFy5gYEjKMfz9AylsaRRgGzvZAAAAAElFTkSuQmCC",QUOTE_IMAGE_RIGHT_DATAURI:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAQAAAAqJXdxAAAAqUlEQVQI1z3KvUpCcRiA8ef9E4JNHhI0aFEacm1o0BsI0Slx8wa8gLauoDnoBhq7DcfWhggONDmJJgqCPA7neJ7p934EOOKOnM8Q7PDElo/4x4lFb2DmuUjcUzS3URnGib9qaPNbuXvBO3sGPHJDRG6fGVdMSeWDP2q99FQdFrz26Gu5Tq7dFMzUvbXy8KXeAj57cOklgA+u1B5AoslLtGIHQMaCVnwDnADZIFIrXsoXrgAAAABJRU5ErkJggg==",
QUOTE_IMAGE_WIDTH:12,QUOTE_IMAGE_HEIGHT:12,quoteField_:function(a){for(var b=0,c;c=this.inputList[b];b++)for(var d=0,e;e=c.fieldRow[d];d++)if(a==e.name){c.insertFieldAt(d,this.newQuote_(!0));c.insertFieldAt(d+2,this.newQuote_(!1));return}console.warn('field named "'+a+'" not found in '+this.toDevString())},newQuote_:function(a){a=this.RTL?!a:a;return new Blockly.FieldImage(a?this.QUOTE_IMAGE_LEFT_DATAURI:this.QUOTE_IMAGE_RIGHT_DATAURI,this.QUOTE_IMAGE_WIDTH,this.QUOTE_IMAGE_HEIGHT,a?"\u201c":"\u201d")}};
Blockly.Constants.Text.TEXT_QUOTES_EXTENSION=function(){this.mixin(Blockly.Constants.Text.QUOTE_IMAGE_MIXIN);this.quoteField_("TEXT")};
Blockly.Constants.Text.TEXT_JOIN_MUTATOR_MIXIN={mutationToDom:function(){var a=Blockly.utils.xml.createElement("mutation");a.setAttribute("items",this.itemCount_);return a},domToMutation:function(a){this.itemCount_=parseInt(a.getAttribute("items"),10);this.updateShape_()},decompose:function(a){var b=a.newBlock("text_create_join_container");b.initSvg();for(var c=b.getInput("STACK").connection,d=0;d<this.itemCount_;d++){var e=a.newBlock("text_create_join_item");e.initSvg();c.connect(e.previousConnection);
c=e.nextConnection}return b},compose:function(a){var b=a.getInputTargetBlock("STACK");for(a=[];b;)a.push(b.valueConnection_),b=b.nextConnection&&b.nextConnection.targetBlock();for(b=0;b<this.itemCount_;b++){var c=this.getInput("ADD"+b).connection.targetConnection;c&&-1==a.indexOf(c)&&c.disconnect()}this.itemCount_=a.length;this.updateShape_();for(b=0;b<this.itemCount_;b++)Blockly.Mutator.reconnect(a[b],this,"ADD"+b)},saveConnections:function(a){a=a.getInputTargetBlock("STACK");for(var b=0;a;){var c=
this.getInput("ADD"+b);a.valueConnection_=c&&c.connection.targetConnection;b++;a=a.nextConnection&&a.nextConnection.targetBlock()}},updateShape_:function(){this.itemCount_&&this.getInput("EMPTY")?this.removeInput("EMPTY"):this.itemCount_||this.getInput("EMPTY")||this.appendDummyInput("EMPTY").appendField(this.newQuote_(!0)).appendField(this.newQuote_(!1));for(var a=0;a<this.itemCount_;a++)if(!this.getInput("ADD"+a)){var b=this.appendValueInput("ADD"+a).setAlign(Blockly.ALIGN_RIGHT);0==a&&b.appendField(Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH)}for(;this.getInput("ADD"+
a);)this.removeInput("ADD"+a),a++}};Blockly.Constants.Text.TEXT_JOIN_EXTENSION=function(){this.mixin(Blockly.Constants.Text.QUOTE_IMAGE_MIXIN);this.itemCount_=2;this.updateShape_();this.setMutator(new Blockly.Mutator(["text_create_join_item"]))};Blockly.Extensions.register("text_append_tooltip",Blockly.Extensions.buildTooltipWithFieldText("%{BKY_TEXT_APPEND_TOOLTIP}","VAR"));
Blockly.Constants.Text.TEXT_INDEXOF_TOOLTIP_EXTENSION=function(){var a=this;this.setTooltip(function(){return Blockly.Msg.TEXT_INDEXOF_TOOLTIP.replace("%1",a.workspace.options.oneBasedIndex?"0":"-1")})};
Blockly.Constants.Text.TEXT_CHARAT_MUTATOR_MIXIN={mutationToDom:function(){var a=Blockly.utils.xml.createElement("mutation");a.setAttribute("at",!!this.isAt_);return a},domToMutation:function(a){a="false"!=a.getAttribute("at");this.updateAt_(a)},updateAt_:function(a){this.removeInput("AT",!0);this.removeInput("ORDINAL",!0);a&&(this.appendValueInput("AT").setCheck("Number"),Blockly.Msg.ORDINAL_NUMBER_SUFFIX&&this.appendDummyInput("ORDINAL").appendField(Blockly.Msg.ORDINAL_NUMBER_SUFFIX));Blockly.Msg.TEXT_CHARAT_TAIL&&
(this.removeInput("TAIL",!0),this.appendDummyInput("TAIL").appendField(Blockly.Msg.TEXT_CHARAT_TAIL));this.isAt_=a}};
Blockly.Constants.Text.TEXT_CHARAT_EXTENSION=function(){this.getField("WHERE").setValidator(function(a){a="FROM_START"==a||"FROM_END"==a;a!=this.isAt_&&this.getSourceBlock().updateAt_(a)});this.updateAt_(!0);var a=this;this.setTooltip(function(){var b=a.getFieldValue("WHERE"),c=Blockly.Msg.TEXT_CHARAT_TOOLTIP;("FROM_START"==b||"FROM_END"==b)&&(b="FROM_START"==b?Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP:Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP)&&(c+=" "+b.replace("%1",a.workspace.options.oneBasedIndex?
"#1":"#0"));return c})};Blockly.Extensions.register("text_indexOf_tooltip",Blockly.Constants.Text.TEXT_INDEXOF_TOOLTIP_EXTENSION);Blockly.Extensions.register("text_quotes",Blockly.Constants.Text.TEXT_QUOTES_EXTENSION);Blockly.Extensions.registerMutator("text_join_mutator",Blockly.Constants.Text.TEXT_JOIN_MUTATOR_MIXIN,Blockly.Constants.Text.TEXT_JOIN_EXTENSION);Blockly.Extensions.registerMutator("text_charAt_mutator",Blockly.Constants.Text.TEXT_CHARAT_MUTATOR_MIXIN,Blockly.Constants.Text.TEXT_CHARAT_EXTENSION);Blockly.Blocks.variables={};Blockly.Constants.Variables={};Blockly.Constants.Variables.HUE=330;
Blockly.defineBlocksWithJsonArray([{type:"variables_get",message0:"%1",args0:[{type:"field_variable",name:"VAR",variable:"%{BKY_VARIABLES_DEFAULT_NAME}"}],output:null,style:"variable_blocks",helpUrl:"%{BKY_VARIABLES_GET_HELPURL}",tooltip:"%{BKY_VARIABLES_GET_TOOLTIP}",extensions:["contextMenu_variableSetterGetter"]},{type:"variables_set",message0:"%{BKY_VARIABLES_SET}",args0:[{type:"field_variable",name:"VAR",variable:"%{BKY_VARIABLES_DEFAULT_NAME}"},{type:"input_value",name:"VALUE"}],previousStatement:null,
nextStatement:null,style:"variable_blocks",tooltip:"%{BKY_VARIABLES_SET_TOOLTIP}",helpUrl:"%{BKY_VARIABLES_SET_HELPURL}",extensions:["contextMenu_variableSetterGetter"]}]);
Blockly.Constants.Variables.CUSTOM_CONTEXT_MENU_VARIABLE_GETTER_SETTER_MIXIN={customContextMenu:function(a){if(!this.isInFlyout){if("variables_get"==this.type)var b="variables_set",c=Blockly.Msg.VARIABLES_GET_CREATE_SET;else b="variables_get",c=Blockly.Msg.VARIABLES_SET_CREATE_GET;var d={enabled:0<this.workspace.remainingCapacity()},e=this.getField("VAR").getText();d.text=c.replace("%1",e);c=Blockly.utils.xml.createElement("field");c.setAttribute("name","VAR");c.appendChild(Blockly.utils.xml.createTextNode(e));
e=Blockly.utils.xml.createElement("block");e.setAttribute("type",b);e.appendChild(c);d.callback=Blockly.ContextMenu.callbackFactory(this,e);a.push(d)}else if("variables_get"==this.type||"variables_get_reporter"==this.type)b={text:Blockly.Msg.RENAME_VARIABLE,enabled:!0,callback:Blockly.Constants.Variables.RENAME_OPTION_CALLBACK_FACTORY(this)},e=this.getField("VAR").getText(),d={text:Blockly.Msg.DELETE_VARIABLE.replace("%1",e),enabled:!0,callback:Blockly.Constants.Variables.DELETE_OPTION_CALLBACK_FACTORY(this)},
a.unshift(b),a.unshift(d)}};Blockly.Constants.Variables.RENAME_OPTION_CALLBACK_FACTORY=function(a){return function(){var b=a.workspace,c=a.getField("VAR").getVariable();Blockly.Variables.renameVariable(b,c)}};Blockly.Constants.Variables.DELETE_OPTION_CALLBACK_FACTORY=function(a){return function(){var b=a.workspace,c=a.getField("VAR").getVariable();b.deleteVariableById(c.getId());b.refreshToolboxSelection()}};Blockly.Extensions.registerMixin("contextMenu_variableSetterGetter",Blockly.Constants.Variables.CUSTOM_CONTEXT_MENU_VARIABLE_GETTER_SETTER_MIXIN);Blockly.Constants.VariablesDynamic={};Blockly.Constants.VariablesDynamic.HUE=310;
Blockly.defineBlocksWithJsonArray([{type:"variables_get_dynamic",message0:"%1",args0:[{type:"field_variable",name:"VAR",variable:"%{BKY_VARIABLES_DEFAULT_NAME}"}],output:null,style:"variable_dynamic_blocks",helpUrl:"%{BKY_VARIABLES_GET_HELPURL}",tooltip:"%{BKY_VARIABLES_GET_TOOLTIP}",extensions:["contextMenu_variableDynamicSetterGetter"]},{type:"variables_set_dynamic",message0:"%{BKY_VARIABLES_SET}",args0:[{type:"field_variable",name:"VAR",variable:"%{BKY_VARIABLES_DEFAULT_NAME}"},{type:"input_value",
name:"VALUE"}],previousStatement:null,nextStatement:null,style:"variable_dynamic_blocks",tooltip:"%{BKY_VARIABLES_SET_TOOLTIP}",helpUrl:"%{BKY_VARIABLES_SET_HELPURL}",extensions:["contextMenu_variableDynamicSetterGetter"]}]);
Blockly.Constants.VariablesDynamic.CUSTOM_CONTEXT_MENU_VARIABLE_GETTER_SETTER_MIXIN={customContextMenu:function(a){if(!this.isInFlyout){var b=this.getFieldValue("VAR");var c=this.workspace.getVariableById(b).type;if("variables_get_dynamic"==this.type){b="variables_set_dynamic";var d=Blockly.Msg.VARIABLES_GET_CREATE_SET}else b="variables_get_dynamic",d=Blockly.Msg.VARIABLES_SET_CREATE_GET;var e={enabled:0<this.workspace.remainingCapacity()},f=this.getField("VAR").getText();e.text=d.replace("%1",f);
d=Blockly.utils.xml.createElement("field");d.setAttribute("name","VAR");d.setAttribute("variabletype",c);d.appendChild(Blockly.utils.xml.createTextNode(f));f=Blockly.utils.xml.createElement("block");f.setAttribute("type",b);f.appendChild(d);e.callback=Blockly.ContextMenu.callbackFactory(this,f);a.push(e)}else if("variables_get_dynamic"==this.type||"variables_get_reporter_dynamic"==this.type)b={text:Blockly.Msg.RENAME_VARIABLE,enabled:!0,callback:Blockly.Constants.Variables.RENAME_OPTION_CALLBACK_FACTORY(this)},
f=this.getField("VAR").getText(),e={text:Blockly.Msg.DELETE_VARIABLE.replace("%1",f),enabled:!0,callback:Blockly.Constants.Variables.DELETE_OPTION_CALLBACK_FACTORY(this)},a.unshift(b),a.unshift(e)},onchange:function(a){a=this.getFieldValue("VAR");a=Blockly.Variables.getVariable(this.workspace,a);"variables_get_dynamic"==this.type?this.outputConnection.setCheck(a.type):this.getInput("VALUE").connection.setCheck(a.type)}};
Blockly.Constants.VariablesDynamic.RENAME_OPTION_CALLBACK_FACTORY=function(a){return function(){var b=a.workspace,c=a.getField("VAR").getVariable();Blockly.Variables.renameVariable(b,c)}};Blockly.Constants.VariablesDynamic.DELETE_OPTION_CALLBACK_FACTORY=function(a){return function(){var b=a.workspace,c=a.getField("VAR").getVariable();b.deleteVariableById(c.getId());b.refreshToolboxSelection()}};Blockly.Extensions.registerMixin("contextMenu_variableDynamicSetterGetter",Blockly.Constants.VariablesDynamic.CUSTOM_CONTEXT_MENU_VARIABLE_GETTER_SETTER_MIXIN);

View File

@ -0,0 +1,102 @@
// Do not edit this file; automatically generated by gulp.
'use strict';
Blockly.JavaScript=new Blockly.Generator("JavaScript");Blockly.JavaScript.addReservedWords("break,case,catch,class,const,continue,debugger,default,delete,do,else,export,extends,finally,for,function,if,import,in,instanceof,new,return,super,switch,this,throw,try,typeof,var,void,while,with,yield,enum,implements,interface,let,package,private,protected,public,static,await,null,true,false,arguments,"+Object.getOwnPropertyNames(Blockly.utils.global).join(","));
Blockly.JavaScript.ORDER_ATOMIC=0;Blockly.JavaScript.ORDER_NEW=1.1;Blockly.JavaScript.ORDER_MEMBER=1.2;Blockly.JavaScript.ORDER_FUNCTION_CALL=2;Blockly.JavaScript.ORDER_INCREMENT=3;Blockly.JavaScript.ORDER_DECREMENT=3;Blockly.JavaScript.ORDER_BITWISE_NOT=4.1;Blockly.JavaScript.ORDER_UNARY_PLUS=4.2;Blockly.JavaScript.ORDER_UNARY_NEGATION=4.3;Blockly.JavaScript.ORDER_LOGICAL_NOT=4.4;Blockly.JavaScript.ORDER_TYPEOF=4.5;Blockly.JavaScript.ORDER_VOID=4.6;Blockly.JavaScript.ORDER_DELETE=4.7;
Blockly.JavaScript.ORDER_AWAIT=4.8;Blockly.JavaScript.ORDER_EXPONENTIATION=5;Blockly.JavaScript.ORDER_MULTIPLICATION=5.1;Blockly.JavaScript.ORDER_DIVISION=5.2;Blockly.JavaScript.ORDER_MODULUS=5.3;Blockly.JavaScript.ORDER_SUBTRACTION=6.1;Blockly.JavaScript.ORDER_ADDITION=6.2;Blockly.JavaScript.ORDER_BITWISE_SHIFT=7;Blockly.JavaScript.ORDER_RELATIONAL=8;Blockly.JavaScript.ORDER_IN=8;Blockly.JavaScript.ORDER_INSTANCEOF=8;Blockly.JavaScript.ORDER_EQUALITY=9;Blockly.JavaScript.ORDER_BITWISE_AND=10;
Blockly.JavaScript.ORDER_BITWISE_XOR=11;Blockly.JavaScript.ORDER_BITWISE_OR=12;Blockly.JavaScript.ORDER_LOGICAL_AND=13;Blockly.JavaScript.ORDER_LOGICAL_OR=14;Blockly.JavaScript.ORDER_CONDITIONAL=15;Blockly.JavaScript.ORDER_ASSIGNMENT=16;Blockly.JavaScript.ORDER_YIELD=17;Blockly.JavaScript.ORDER_COMMA=18;Blockly.JavaScript.ORDER_NONE=99;
Blockly.JavaScript.ORDER_OVERRIDES=[[Blockly.JavaScript.ORDER_FUNCTION_CALL,Blockly.JavaScript.ORDER_MEMBER],[Blockly.JavaScript.ORDER_FUNCTION_CALL,Blockly.JavaScript.ORDER_FUNCTION_CALL],[Blockly.JavaScript.ORDER_MEMBER,Blockly.JavaScript.ORDER_MEMBER],[Blockly.JavaScript.ORDER_MEMBER,Blockly.JavaScript.ORDER_FUNCTION_CALL],[Blockly.JavaScript.ORDER_LOGICAL_NOT,Blockly.JavaScript.ORDER_LOGICAL_NOT],[Blockly.JavaScript.ORDER_MULTIPLICATION,Blockly.JavaScript.ORDER_MULTIPLICATION],[Blockly.JavaScript.ORDER_ADDITION,
Blockly.JavaScript.ORDER_ADDITION],[Blockly.JavaScript.ORDER_LOGICAL_AND,Blockly.JavaScript.ORDER_LOGICAL_AND],[Blockly.JavaScript.ORDER_LOGICAL_OR,Blockly.JavaScript.ORDER_LOGICAL_OR]];
Blockly.JavaScript.init=function(a){Blockly.JavaScript.definitions_=Object.create(null);Blockly.JavaScript.functionNames_=Object.create(null);Blockly.JavaScript.variableDB_?Blockly.JavaScript.variableDB_.reset():Blockly.JavaScript.variableDB_=new Blockly.Names(Blockly.JavaScript.RESERVED_WORDS_);Blockly.JavaScript.variableDB_.setVariableMap(a.getVariableMap());for(var b=[],c=Blockly.Variables.allDeveloperVariables(a),d=0;d<c.length;d++)b.push(Blockly.JavaScript.variableDB_.getName(c[d],Blockly.Names.DEVELOPER_VARIABLE_TYPE));
a=Blockly.Variables.allUsedVarModels(a);for(d=0;d<a.length;d++)b.push(Blockly.JavaScript.variableDB_.getName(a[d].getId(),Blockly.VARIABLE_CATEGORY_NAME));b.length&&(Blockly.JavaScript.definitions_.variables="var "+b.join(", ")+";")};
Blockly.JavaScript.finish=function(a){var b=[],c;for(c in Blockly.JavaScript.definitions_)b.push(Blockly.JavaScript.definitions_[c]);delete Blockly.JavaScript.definitions_;delete Blockly.JavaScript.functionNames_;Blockly.JavaScript.variableDB_.reset();return b.join("\n\n")+"\n\n\n"+a};Blockly.JavaScript.scrubNakedValue=function(a){return a+";\n"};Blockly.JavaScript.quote_=function(a){a=a.replace(/\\/g,"\\\\").replace(/\n/g,"\\\n").replace(/'/g,"\\'");return"'"+a+"'"};
Blockly.JavaScript.multiline_quote_=function(a){return a.split(/\n/g).map(Blockly.JavaScript.quote_).join(" + '\\n' +\n")};
Blockly.JavaScript.scrub_=function(a,b,c){var d="";if(!a.outputConnection||!a.outputConnection.targetConnection){var e=a.getCommentText();e&&(e=Blockly.utils.string.wrap(e,Blockly.JavaScript.COMMENT_WRAP-3),d+=Blockly.JavaScript.prefixLines(e+"\n","// "));for(var f=0;f<a.inputList.length;f++)a.inputList[f].type==Blockly.INPUT_VALUE&&(e=a.inputList[f].connection.targetBlock())&&(e=Blockly.JavaScript.allNestedComments(e))&&(d+=Blockly.JavaScript.prefixLines(e,"// "))}a=a.nextConnection&&a.nextConnection.targetBlock();
c=c?"":Blockly.JavaScript.blockToCode(a);return d+b+c};
Blockly.JavaScript.getAdjusted=function(a,b,c,d,e){c=c||0;e=e||Blockly.JavaScript.ORDER_NONE;a.workspace.options.oneBasedIndex&&c--;var f=a.workspace.options.oneBasedIndex?"1":"0";a=0<c?Blockly.JavaScript.valueToCode(a,b,Blockly.JavaScript.ORDER_ADDITION)||f:0>c?Blockly.JavaScript.valueToCode(a,b,Blockly.JavaScript.ORDER_SUBTRACTION)||f:d?Blockly.JavaScript.valueToCode(a,b,Blockly.JavaScript.ORDER_UNARY_NEGATION)||f:Blockly.JavaScript.valueToCode(a,b,e)||f;if(Blockly.isNumber(a))a=Number(a)+c,d&&
(a=-a);else{if(0<c){a=a+" + "+c;var g=Blockly.JavaScript.ORDER_ADDITION}else 0>c&&(a=a+" - "+-c,g=Blockly.JavaScript.ORDER_SUBTRACTION);d&&(a=c?"-("+a+")":"-"+a,g=Blockly.JavaScript.ORDER_UNARY_NEGATION);g=Math.floor(g);e=Math.floor(e);g&&e>=g&&(a="("+a+")")}return a};Blockly.JavaScript.colour={};Blockly.JavaScript.colour_picker=function(a){return[Blockly.JavaScript.quote_(a.getFieldValue("COLOUR")),Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.colour_random=function(a){return[Blockly.JavaScript.provideFunction_("colourRandom",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"() {"," var num = Math.floor(Math.random() * Math.pow(2, 24));"," return '#' + ('00000' + num.toString(16)).substr(-6);","}"])+"()",Blockly.JavaScript.ORDER_FUNCTION_CALL]};
Blockly.JavaScript.colour_rgb=function(a){var b=Blockly.JavaScript.valueToCode(a,"RED",Blockly.JavaScript.ORDER_COMMA)||0,c=Blockly.JavaScript.valueToCode(a,"GREEN",Blockly.JavaScript.ORDER_COMMA)||0;a=Blockly.JavaScript.valueToCode(a,"BLUE",Blockly.JavaScript.ORDER_COMMA)||0;return[Blockly.JavaScript.provideFunction_("colourRgb",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(r, g, b) {"," r = Math.max(Math.min(Number(r), 100), 0) * 2.55;"," g = Math.max(Math.min(Number(g), 100), 0) * 2.55;",
" b = Math.max(Math.min(Number(b), 100), 0) * 2.55;"," r = ('0' + (Math.round(r) || 0).toString(16)).slice(-2);"," g = ('0' + (Math.round(g) || 0).toString(16)).slice(-2);"," b = ('0' + (Math.round(b) || 0).toString(16)).slice(-2);"," return '#' + r + g + b;","}"])+"("+b+", "+c+", "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]};
Blockly.JavaScript.colour_blend=function(a){var b=Blockly.JavaScript.valueToCode(a,"COLOUR1",Blockly.JavaScript.ORDER_COMMA)||"'#000000'",c=Blockly.JavaScript.valueToCode(a,"COLOUR2",Blockly.JavaScript.ORDER_COMMA)||"'#000000'";a=Blockly.JavaScript.valueToCode(a,"RATIO",Blockly.JavaScript.ORDER_COMMA)||.5;return[Blockly.JavaScript.provideFunction_("colourBlend",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(c1, c2, ratio) {"," ratio = Math.max(Math.min(Number(ratio), 1), 0);"," var r1 = parseInt(c1.substring(1, 3), 16);",
" var g1 = parseInt(c1.substring(3, 5), 16);"," var b1 = parseInt(c1.substring(5, 7), 16);"," var r2 = parseInt(c2.substring(1, 3), 16);"," var g2 = parseInt(c2.substring(3, 5), 16);"," var b2 = parseInt(c2.substring(5, 7), 16);"," var r = Math.round(r1 * (1 - ratio) + r2 * ratio);"," var g = Math.round(g1 * (1 - ratio) + g2 * ratio);"," var b = Math.round(b1 * (1 - ratio) + b2 * ratio);"," r = ('0' + (r || 0).toString(16)).slice(-2);"," g = ('0' + (g || 0).toString(16)).slice(-2);"," b = ('0' + (b || 0).toString(16)).slice(-2);",
" return '#' + r + g + b;","}"])+"("+b+", "+c+", "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.lists={};Blockly.JavaScript.lists_create_empty=function(a){return["[]",Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.lists_create_with=function(a){for(var b=Array(a.itemCount_),c=0;c<a.itemCount_;c++)b[c]=Blockly.JavaScript.valueToCode(a,"ADD"+c,Blockly.JavaScript.ORDER_COMMA)||"null";return["["+b.join(", ")+"]",Blockly.JavaScript.ORDER_ATOMIC]};
Blockly.JavaScript.lists_repeat=function(a){var b=Blockly.JavaScript.provideFunction_("listsRepeat",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(value, n) {"," var array = [];"," for (var i = 0; i < n; i++) {"," array[i] = value;"," }"," return array;","}"]),c=Blockly.JavaScript.valueToCode(a,"ITEM",Blockly.JavaScript.ORDER_COMMA)||"null";a=Blockly.JavaScript.valueToCode(a,"NUM",Blockly.JavaScript.ORDER_COMMA)||"0";return[b+"("+c+", "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]};
Blockly.JavaScript.lists_length=function(a){return[(Blockly.JavaScript.valueToCode(a,"VALUE",Blockly.JavaScript.ORDER_MEMBER)||"[]")+".length",Blockly.JavaScript.ORDER_MEMBER]};Blockly.JavaScript.lists_isEmpty=function(a){return["!"+(Blockly.JavaScript.valueToCode(a,"VALUE",Blockly.JavaScript.ORDER_MEMBER)||"[]")+".length",Blockly.JavaScript.ORDER_LOGICAL_NOT]};
Blockly.JavaScript.lists_indexOf=function(a){var b="FIRST"==a.getFieldValue("END")?"indexOf":"lastIndexOf",c=Blockly.JavaScript.valueToCode(a,"FIND",Blockly.JavaScript.ORDER_NONE)||"''";b=(Blockly.JavaScript.valueToCode(a,"VALUE",Blockly.JavaScript.ORDER_MEMBER)||"[]")+"."+b+"("+c+")";return a.workspace.options.oneBasedIndex?[b+" + 1",Blockly.JavaScript.ORDER_ADDITION]:[b,Blockly.JavaScript.ORDER_FUNCTION_CALL]};
Blockly.JavaScript.lists_getIndex=function(a){var b=a.getFieldValue("MODE")||"GET",c=a.getFieldValue("WHERE")||"FROM_START",d=Blockly.JavaScript.valueToCode(a,"VALUE","RANDOM"==c?Blockly.JavaScript.ORDER_COMMA:Blockly.JavaScript.ORDER_MEMBER)||"[]";switch(c){case "FIRST":if("GET"==b)return[d+"[0]",Blockly.JavaScript.ORDER_MEMBER];if("GET_REMOVE"==b)return[d+".shift()",Blockly.JavaScript.ORDER_MEMBER];if("REMOVE"==b)return d+".shift();\n";break;case "LAST":if("GET"==b)return[d+".slice(-1)[0]",Blockly.JavaScript.ORDER_MEMBER];
if("GET_REMOVE"==b)return[d+".pop()",Blockly.JavaScript.ORDER_MEMBER];if("REMOVE"==b)return d+".pop();\n";break;case "FROM_START":a=Blockly.JavaScript.getAdjusted(a,"AT");if("GET"==b)return[d+"["+a+"]",Blockly.JavaScript.ORDER_MEMBER];if("GET_REMOVE"==b)return[d+".splice("+a+", 1)[0]",Blockly.JavaScript.ORDER_FUNCTION_CALL];if("REMOVE"==b)return d+".splice("+a+", 1);\n";break;case "FROM_END":a=Blockly.JavaScript.getAdjusted(a,"AT",1,!0);if("GET"==b)return[d+".slice("+a+")[0]",Blockly.JavaScript.ORDER_FUNCTION_CALL];
if("GET_REMOVE"==b)return[d+".splice("+a+", 1)[0]",Blockly.JavaScript.ORDER_FUNCTION_CALL];if("REMOVE"==b)return d+".splice("+a+", 1);";break;case "RANDOM":d=Blockly.JavaScript.provideFunction_("listsGetRandomItem",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(list, remove) {"," var x = Math.floor(Math.random() * list.length);"," if (remove) {"," return list.splice(x, 1)[0];"," } else {"," return list[x];"," }","}"])+"("+d+", "+("GET"!=b)+")";if("GET"==b||"GET_REMOVE"==b)return[d,
Blockly.JavaScript.ORDER_FUNCTION_CALL];if("REMOVE"==b)return d+";\n"}throw Error("Unhandled combination (lists_getIndex).");};
Blockly.JavaScript.lists_setIndex=function(a){function b(){if(c.match(/^\w+$/))return"";var a=Blockly.JavaScript.variableDB_.getDistinctName("tmpList",Blockly.VARIABLE_CATEGORY_NAME),b="var "+a+" = "+c+";\n";c=a;return b}var c=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_MEMBER)||"[]",d=a.getFieldValue("MODE")||"GET",e=a.getFieldValue("WHERE")||"FROM_START",f=Blockly.JavaScript.valueToCode(a,"TO",Blockly.JavaScript.ORDER_ASSIGNMENT)||"null";switch(e){case "FIRST":if("SET"==d)return c+
"[0] = "+f+";\n";if("INSERT"==d)return c+".unshift("+f+");\n";break;case "LAST":if("SET"==d)return a=b(),a+(c+"["+c+".length - 1] = "+f+";\n");if("INSERT"==d)return c+".push("+f+");\n";break;case "FROM_START":e=Blockly.JavaScript.getAdjusted(a,"AT");if("SET"==d)return c+"["+e+"] = "+f+";\n";if("INSERT"==d)return c+".splice("+e+", 0, "+f+");\n";break;case "FROM_END":e=Blockly.JavaScript.getAdjusted(a,"AT",1,!1,Blockly.JavaScript.ORDER_SUBTRACTION);a=b();if("SET"==d)return a+(c+"["+c+".length - "+e+
"] = "+f+";\n");if("INSERT"==d)return a+(c+".splice("+c+".length - "+e+", 0, "+f+");\n");break;case "RANDOM":a=b();e=Blockly.JavaScript.variableDB_.getDistinctName("tmpX",Blockly.VARIABLE_CATEGORY_NAME);a+="var "+e+" = Math.floor(Math.random() * "+c+".length);\n";if("SET"==d)return a+(c+"["+e+"] = "+f+";\n");if("INSERT"==d)return a+(c+".splice("+e+", 0, "+f+");\n")}throw Error("Unhandled combination (lists_setIndex).");};
Blockly.JavaScript.lists.getIndex_=function(a,b,c){return"FIRST"==b?"0":"FROM_END"==b?a+".length - 1 - "+c:"LAST"==b?a+".length - 1":c};
Blockly.JavaScript.lists_getSublist=function(a){var b=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_MEMBER)||"[]",c=a.getFieldValue("WHERE1"),d=a.getFieldValue("WHERE2");if("FIRST"==c&&"LAST"==d)b+=".slice(0)";else if(b.match(/^\w+$/)||"FROM_END"!=c&&"FROM_START"==d){switch(c){case "FROM_START":var e=Blockly.JavaScript.getAdjusted(a,"AT1");break;case "FROM_END":e=Blockly.JavaScript.getAdjusted(a,"AT1",1,!1,Blockly.JavaScript.ORDER_SUBTRACTION);e=b+".length - "+e;break;case "FIRST":e=
"0";break;default:throw Error("Unhandled option (lists_getSublist).");}switch(d){case "FROM_START":a=Blockly.JavaScript.getAdjusted(a,"AT2",1);break;case "FROM_END":a=Blockly.JavaScript.getAdjusted(a,"AT2",0,!1,Blockly.JavaScript.ORDER_SUBTRACTION);a=b+".length - "+a;break;case "LAST":a=b+".length";break;default:throw Error("Unhandled option (lists_getSublist).");}b=b+".slice("+e+", "+a+")"}else{e=Blockly.JavaScript.getAdjusted(a,"AT1");a=Blockly.JavaScript.getAdjusted(a,"AT2");var f=Blockly.JavaScript.lists.getIndex_,
g={FIRST:"First",LAST:"Last",FROM_START:"FromStart",FROM_END:"FromEnd"};b=Blockly.JavaScript.provideFunction_("subsequence"+g[c]+g[d],["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(sequence"+("FROM_END"==c||"FROM_START"==c?", at1":"")+("FROM_END"==d||"FROM_START"==d?", at2":"")+") {"," var start = "+f("sequence",c,"at1")+";"," var end = "+f("sequence",d,"at2")+" + 1;"," return sequence.slice(start, end);","}"])+"("+b+("FROM_END"==c||"FROM_START"==c?", "+e:"")+("FROM_END"==d||"FROM_START"==
d?", "+a:"")+")"}return[b,Blockly.JavaScript.ORDER_FUNCTION_CALL]};
Blockly.JavaScript.lists_sort=function(a){var b=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_FUNCTION_CALL)||"[]",c="1"===a.getFieldValue("DIRECTION")?1:-1;a=a.getFieldValue("TYPE");var d=Blockly.JavaScript.provideFunction_("listsGetSortCompare",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(type, direction) {"," var compareFuncs = {",' "NUMERIC": function(a, b) {'," return Number(a) - Number(b); },",' "TEXT": function(a, b) {'," return a.toString() > b.toString() ? 1 : -1; },",
' "IGNORE_CASE": function(a, b) {'," return a.toString().toLowerCase() > b.toString().toLowerCase() ? 1 : -1; },"," };"," var compare = compareFuncs[type];"," return function(a, b) { return compare(a, b) * direction; }","}"]);return[b+".slice().sort("+d+'("'+a+'", '+c+"))",Blockly.JavaScript.ORDER_FUNCTION_CALL]};
Blockly.JavaScript.lists_split=function(a){var b=Blockly.JavaScript.valueToCode(a,"INPUT",Blockly.JavaScript.ORDER_MEMBER),c=Blockly.JavaScript.valueToCode(a,"DELIM",Blockly.JavaScript.ORDER_NONE)||"''";a=a.getFieldValue("MODE");if("SPLIT"==a)b||(b="''"),a="split";else if("JOIN"==a)b||(b="[]"),a="join";else throw Error("Unknown mode: "+a);return[b+"."+a+"("+c+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]};
Blockly.JavaScript.lists_reverse=function(a){return[(Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_FUNCTION_CALL)||"[]")+".slice().reverse()",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.logic={};
Blockly.JavaScript.controls_if=function(a){var b=0,c="";Blockly.JavaScript.STATEMENT_PREFIX&&(c+=Blockly.JavaScript.injectId(Blockly.JavaScript.STATEMENT_PREFIX,a));do{var d=Blockly.JavaScript.valueToCode(a,"IF"+b,Blockly.JavaScript.ORDER_NONE)||"false";var e=Blockly.JavaScript.statementToCode(a,"DO"+b);Blockly.JavaScript.STATEMENT_SUFFIX&&(e=Blockly.JavaScript.prefixLines(Blockly.JavaScript.injectId(Blockly.JavaScript.STATEMENT_SUFFIX,a),Blockly.JavaScript.INDENT)+e);c+=(0<b?" else ":"")+"if ("+
d+") {\n"+e+"}";++b}while(a.getInput("IF"+b));if(a.getInput("ELSE")||Blockly.JavaScript.STATEMENT_SUFFIX)e=Blockly.JavaScript.statementToCode(a,"ELSE"),Blockly.JavaScript.STATEMENT_SUFFIX&&(e=Blockly.JavaScript.prefixLines(Blockly.JavaScript.injectId(Blockly.JavaScript.STATEMENT_SUFFIX,a),Blockly.JavaScript.INDENT)+e),c+=" else {\n"+e+"}";return c+"\n"};Blockly.JavaScript.controls_ifelse=Blockly.JavaScript.controls_if;
Blockly.JavaScript.logic_compare=function(a){var b={EQ:"==",NEQ:"!=",LT:"<",LTE:"<=",GT:">",GTE:">="}[a.getFieldValue("OP")],c="=="==b||"!="==b?Blockly.JavaScript.ORDER_EQUALITY:Blockly.JavaScript.ORDER_RELATIONAL,d=Blockly.JavaScript.valueToCode(a,"A",c)||"0";a=Blockly.JavaScript.valueToCode(a,"B",c)||"0";return[d+" "+b+" "+a,c]};
Blockly.JavaScript.logic_operation=function(a){var b="AND"==a.getFieldValue("OP")?"&&":"||",c="&&"==b?Blockly.JavaScript.ORDER_LOGICAL_AND:Blockly.JavaScript.ORDER_LOGICAL_OR,d=Blockly.JavaScript.valueToCode(a,"A",c);a=Blockly.JavaScript.valueToCode(a,"B",c);if(d||a){var e="&&"==b?"true":"false";d||(d=e);a||(a=e)}else a=d="false";return[d+" "+b+" "+a,c]};
Blockly.JavaScript.logic_negate=function(a){var b=Blockly.JavaScript.ORDER_LOGICAL_NOT;return["!"+(Blockly.JavaScript.valueToCode(a,"BOOL",b)||"true"),b]};Blockly.JavaScript.logic_boolean=function(a){return["TRUE"==a.getFieldValue("BOOL")?"true":"false",Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.logic_null=function(a){return["null",Blockly.JavaScript.ORDER_ATOMIC]};
Blockly.JavaScript.logic_ternary=function(a){var b=Blockly.JavaScript.valueToCode(a,"IF",Blockly.JavaScript.ORDER_CONDITIONAL)||"false",c=Blockly.JavaScript.valueToCode(a,"THEN",Blockly.JavaScript.ORDER_CONDITIONAL)||"null";a=Blockly.JavaScript.valueToCode(a,"ELSE",Blockly.JavaScript.ORDER_CONDITIONAL)||"null";return[b+" ? "+c+" : "+a,Blockly.JavaScript.ORDER_CONDITIONAL]};Blockly.JavaScript.loops={};
Blockly.JavaScript.controls_repeat_ext=function(a){var b=a.getField("TIMES")?String(Number(a.getFieldValue("TIMES"))):Blockly.JavaScript.valueToCode(a,"TIMES",Blockly.JavaScript.ORDER_ASSIGNMENT)||"0",c=Blockly.JavaScript.statementToCode(a,"DO");c=Blockly.JavaScript.addLoopTrap(c,a);a="";var d=Blockly.JavaScript.variableDB_.getDistinctName("count",Blockly.VARIABLE_CATEGORY_NAME),e=b;b.match(/^\w+$/)||Blockly.isNumber(b)||(e=Blockly.JavaScript.variableDB_.getDistinctName("repeat_end",Blockly.VARIABLE_CATEGORY_NAME),
a+="var "+e+" = "+b+";\n");return a+("for (var "+d+" = 0; "+d+" < "+e+"; "+d+"++) {\n"+c+"}\n")};Blockly.JavaScript.controls_repeat=Blockly.JavaScript.controls_repeat_ext;
Blockly.JavaScript.controls_whileUntil=function(a){var b="UNTIL"==a.getFieldValue("MODE"),c=Blockly.JavaScript.valueToCode(a,"BOOL",b?Blockly.JavaScript.ORDER_LOGICAL_NOT:Blockly.JavaScript.ORDER_NONE)||"false",d=Blockly.JavaScript.statementToCode(a,"DO");d=Blockly.JavaScript.addLoopTrap(d,a);b&&(c="!"+c);return"while ("+c+") {\n"+d+"}\n"};
Blockly.JavaScript.controls_for=function(a){var b=Blockly.JavaScript.variableDB_.getName(a.getFieldValue("VAR"),Blockly.VARIABLE_CATEGORY_NAME),c=Blockly.JavaScript.valueToCode(a,"FROM",Blockly.JavaScript.ORDER_ASSIGNMENT)||"0",d=Blockly.JavaScript.valueToCode(a,"TO",Blockly.JavaScript.ORDER_ASSIGNMENT)||"0",e=Blockly.JavaScript.valueToCode(a,"BY",Blockly.JavaScript.ORDER_ASSIGNMENT)||"1",f=Blockly.JavaScript.statementToCode(a,"DO");f=Blockly.JavaScript.addLoopTrap(f,a);if(Blockly.isNumber(c)&&Blockly.isNumber(d)&&
Blockly.isNumber(e)){var g=Number(c)<=Number(d);a="for ("+b+" = "+c+"; "+b+(g?" <= ":" >= ")+d+"; "+b;b=Math.abs(Number(e));a=(1==b?a+(g?"++":"--"):a+((g?" += ":" -= ")+b))+(") {\n"+f+"}\n")}else a="",g=c,c.match(/^\w+$/)||Blockly.isNumber(c)||(g=Blockly.JavaScript.variableDB_.getDistinctName(b+"_start",Blockly.VARIABLE_CATEGORY_NAME),a+="var "+g+" = "+c+";\n"),c=d,d.match(/^\w+$/)||Blockly.isNumber(d)||(c=Blockly.JavaScript.variableDB_.getDistinctName(b+"_end",Blockly.VARIABLE_CATEGORY_NAME),a+=
"var "+c+" = "+d+";\n"),d=Blockly.JavaScript.variableDB_.getDistinctName(b+"_inc",Blockly.VARIABLE_CATEGORY_NAME),a+="var "+d+" = ",a=Blockly.isNumber(e)?a+(Math.abs(e)+";\n"):a+("Math.abs("+e+");\n"),a=a+("if ("+g+" > "+c+") {\n")+(Blockly.JavaScript.INDENT+d+" = -"+d+";\n"),a+="}\n",a+="for ("+b+" = "+g+"; "+d+" >= 0 ? "+b+" <= "+c+" : "+b+" >= "+c+"; "+b+" += "+d+") {\n"+f+"}\n";return a};
Blockly.JavaScript.controls_forEach=function(a){var b=Blockly.JavaScript.variableDB_.getName(a.getFieldValue("VAR"),Blockly.VARIABLE_CATEGORY_NAME),c=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_ASSIGNMENT)||"[]",d=Blockly.JavaScript.statementToCode(a,"DO");d=Blockly.JavaScript.addLoopTrap(d,a);a="";var e=c;c.match(/^\w+$/)||(e=Blockly.JavaScript.variableDB_.getDistinctName(b+"_list",Blockly.VARIABLE_CATEGORY_NAME),a+="var "+e+" = "+c+";\n");c=Blockly.JavaScript.variableDB_.getDistinctName(b+
"_index",Blockly.VARIABLE_CATEGORY_NAME);d=Blockly.JavaScript.INDENT+b+" = "+e+"["+c+"];\n"+d;return a+("for (var "+c+" in "+e+") {\n"+d+"}\n")};
Blockly.JavaScript.controls_flow_statements=function(a){var b="";Blockly.JavaScript.STATEMENT_PREFIX&&(b+=Blockly.JavaScript.injectId(Blockly.JavaScript.STATEMENT_PREFIX,a));Blockly.JavaScript.STATEMENT_SUFFIX&&(b+=Blockly.JavaScript.injectId(Blockly.JavaScript.STATEMENT_SUFFIX,a));if(Blockly.JavaScript.STATEMENT_PREFIX){var c=Blockly.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN.getSurroundLoop(a);c&&!c.suppressPrefixSuffix&&(b+=Blockly.JavaScript.injectId(Blockly.JavaScript.STATEMENT_PREFIX,
c))}switch(a.getFieldValue("FLOW")){case "BREAK":return b+"break;\n";case "CONTINUE":return b+"continue;\n"}throw Error("Unknown flow statement.");};Blockly.JavaScript.math={};Blockly.JavaScript.math_number=function(a){a=Number(a.getFieldValue("NUM"));return[a,0<=a?Blockly.JavaScript.ORDER_ATOMIC:Blockly.JavaScript.ORDER_UNARY_NEGATION]};
Blockly.JavaScript.math_arithmetic=function(a){var b={ADD:[" + ",Blockly.JavaScript.ORDER_ADDITION],MINUS:[" - ",Blockly.JavaScript.ORDER_SUBTRACTION],MULTIPLY:[" * ",Blockly.JavaScript.ORDER_MULTIPLICATION],DIVIDE:[" / ",Blockly.JavaScript.ORDER_DIVISION],POWER:[null,Blockly.JavaScript.ORDER_COMMA]}[a.getFieldValue("OP")],c=b[0];b=b[1];var d=Blockly.JavaScript.valueToCode(a,"A",b)||"0";a=Blockly.JavaScript.valueToCode(a,"B",b)||"0";return c?[d+c+a,b]:["Math.pow("+d+", "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]};
Blockly.JavaScript.math_single=function(a){var b=a.getFieldValue("OP");if("NEG"==b)return a=Blockly.JavaScript.valueToCode(a,"NUM",Blockly.JavaScript.ORDER_UNARY_NEGATION)||"0","-"==a[0]&&(a=" "+a),["-"+a,Blockly.JavaScript.ORDER_UNARY_NEGATION];a="SIN"==b||"COS"==b||"TAN"==b?Blockly.JavaScript.valueToCode(a,"NUM",Blockly.JavaScript.ORDER_DIVISION)||"0":Blockly.JavaScript.valueToCode(a,"NUM",Blockly.JavaScript.ORDER_NONE)||"0";switch(b){case "ABS":var c="Math.abs("+a+")";break;case "ROOT":c="Math.sqrt("+
a+")";break;case "LN":c="Math.log("+a+")";break;case "EXP":c="Math.exp("+a+")";break;case "POW10":c="Math.pow(10,"+a+")";break;case "ROUND":c="Math.round("+a+")";break;case "ROUNDUP":c="Math.ceil("+a+")";break;case "ROUNDDOWN":c="Math.floor("+a+")";break;case "SIN":c="Math.sin("+a+" / 180 * Math.PI)";break;case "COS":c="Math.cos("+a+" / 180 * Math.PI)";break;case "TAN":c="Math.tan("+a+" / 180 * Math.PI)"}if(c)return[c,Blockly.JavaScript.ORDER_FUNCTION_CALL];switch(b){case "LOG10":c="Math.log("+a+
") / Math.log(10)";break;case "ASIN":c="Math.asin("+a+") / Math.PI * 180";break;case "ACOS":c="Math.acos("+a+") / Math.PI * 180";break;case "ATAN":c="Math.atan("+a+") / Math.PI * 180";break;default:throw Error("Unknown math operator: "+b);}return[c,Blockly.JavaScript.ORDER_DIVISION]};
Blockly.JavaScript.math_constant=function(a){return{PI:["Math.PI",Blockly.JavaScript.ORDER_MEMBER],E:["Math.E",Blockly.JavaScript.ORDER_MEMBER],GOLDEN_RATIO:["(1 + Math.sqrt(5)) / 2",Blockly.JavaScript.ORDER_DIVISION],SQRT2:["Math.SQRT2",Blockly.JavaScript.ORDER_MEMBER],SQRT1_2:["Math.SQRT1_2",Blockly.JavaScript.ORDER_MEMBER],INFINITY:["Infinity",Blockly.JavaScript.ORDER_ATOMIC]}[a.getFieldValue("CONSTANT")]};
Blockly.JavaScript.math_number_property=function(a){var b=Blockly.JavaScript.valueToCode(a,"NUMBER_TO_CHECK",Blockly.JavaScript.ORDER_MODULUS)||"0",c=a.getFieldValue("PROPERTY");if("PRIME"==c)return[Blockly.JavaScript.provideFunction_("mathIsPrime",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(n) {"," // https://en.wikipedia.org/wiki/Primality_test#Naive_methods"," if (n == 2 || n == 3) {"," return true;"," }"," // False if n is NaN, negative, is 1, or not whole."," // And false if n is divisible by 2 or 3.",
" if (isNaN(n) || n <= 1 || n % 1 != 0 || n % 2 == 0 || n % 3 == 0) {"," return false;"," }"," // Check all the numbers of form 6k +/- 1, up to sqrt(n)."," for (var x = 6; x <= Math.sqrt(n) + 1; x += 6) {"," if (n % (x - 1) == 0 || n % (x + 1) == 0) {"," return false;"," }"," }"," return true;","}"])+"("+b+")",Blockly.JavaScript.ORDER_FUNCTION_CALL];switch(c){case "EVEN":var d=b+" % 2 == 0";break;case "ODD":d=b+" % 2 == 1";break;case "WHOLE":d=b+" % 1 == 0";break;case "POSITIVE":d=
b+" > 0";break;case "NEGATIVE":d=b+" < 0";break;case "DIVISIBLE_BY":a=Blockly.JavaScript.valueToCode(a,"DIVISOR",Blockly.JavaScript.ORDER_MODULUS)||"0",d=b+" % "+a+" == 0"}return[d,Blockly.JavaScript.ORDER_EQUALITY]};
Blockly.JavaScript.math_change=function(a){var b=Blockly.JavaScript.valueToCode(a,"DELTA",Blockly.JavaScript.ORDER_ADDITION)||"0";a=Blockly.JavaScript.variableDB_.getName(a.getFieldValue("VAR"),Blockly.VARIABLE_CATEGORY_NAME);return a+" = (typeof "+a+" == 'number' ? "+a+" : 0) + "+b+";\n"};Blockly.JavaScript.math_round=Blockly.JavaScript.math_single;Blockly.JavaScript.math_trig=Blockly.JavaScript.math_single;
Blockly.JavaScript.math_on_list=function(a){var b=a.getFieldValue("OP");switch(b){case "SUM":a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_MEMBER)||"[]";a+=".reduce(function(x, y) {return x + y;})";break;case "MIN":a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_COMMA)||"[]";a="Math.min.apply(null, "+a+")";break;case "MAX":a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_COMMA)||"[]";a="Math.max.apply(null, "+a+")";break;case "AVERAGE":b=Blockly.JavaScript.provideFunction_("mathMean",
["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(myList) {"," return myList.reduce(function(x, y) {return x + y;}) / myList.length;","}"]);a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_NONE)||"[]";a=b+"("+a+")";break;case "MEDIAN":b=Blockly.JavaScript.provideFunction_("mathMedian",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(myList) {"," var localList = myList.filter(function (x) {return typeof x == 'number';});"," if (!localList.length) return null;",
" localList.sort(function(a, b) {return b - a;});"," if (localList.length % 2 == 0) {"," return (localList[localList.length / 2 - 1] + localList[localList.length / 2]) / 2;"," } else {"," return localList[(localList.length - 1) / 2];"," }","}"]);a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_NONE)||"[]";a=b+"("+a+")";break;case "MODE":b=Blockly.JavaScript.provideFunction_("mathModes",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(values) {"," var modes = [];",
" var counts = [];"," var maxCount = 0;"," for (var i = 0; i < values.length; i++) {"," var value = values[i];"," var found = false;"," var thisCount;"," for (var j = 0; j < counts.length; j++) {"," if (counts[j][0] === value) {"," thisCount = ++counts[j][1];"," found = true;"," break;"," }"," }"," if (!found) {"," counts.push([value, 1]);"," thisCount = 1;"," }"," maxCount = Math.max(thisCount, maxCount);"," }"," for (var j = 0; j < counts.length; j++) {",
" if (counts[j][1] == maxCount) {"," modes.push(counts[j][0]);"," }"," }"," return modes;","}"]);a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_NONE)||"[]";a=b+"("+a+")";break;case "STD_DEV":b=Blockly.JavaScript.provideFunction_("mathStandardDeviation",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(numbers) {"," var n = numbers.length;"," if (!n) return null;"," var mean = numbers.reduce(function(x, y) {return x + y;}) / n;"," var variance = 0;",
" for (var j = 0; j < n; j++) {"," variance += Math.pow(numbers[j] - mean, 2);"," }"," variance = variance / n;"," return Math.sqrt(variance);","}"]);a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_NONE)||"[]";a=b+"("+a+")";break;case "RANDOM":b=Blockly.JavaScript.provideFunction_("mathRandomList",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(list) {"," var x = Math.floor(Math.random() * list.length);"," return list[x];","}"]);a=Blockly.JavaScript.valueToCode(a,
"LIST",Blockly.JavaScript.ORDER_NONE)||"[]";a=b+"("+a+")";break;default:throw Error("Unknown operator: "+b);}return[a,Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.math_modulo=function(a){var b=Blockly.JavaScript.valueToCode(a,"DIVIDEND",Blockly.JavaScript.ORDER_MODULUS)||"0";a=Blockly.JavaScript.valueToCode(a,"DIVISOR",Blockly.JavaScript.ORDER_MODULUS)||"0";return[b+" % "+a,Blockly.JavaScript.ORDER_MODULUS]};
Blockly.JavaScript.math_constrain=function(a){var b=Blockly.JavaScript.valueToCode(a,"VALUE",Blockly.JavaScript.ORDER_COMMA)||"0",c=Blockly.JavaScript.valueToCode(a,"LOW",Blockly.JavaScript.ORDER_COMMA)||"0";a=Blockly.JavaScript.valueToCode(a,"HIGH",Blockly.JavaScript.ORDER_COMMA)||"Infinity";return["Math.min(Math.max("+b+", "+c+"), "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]};
Blockly.JavaScript.math_random_int=function(a){var b=Blockly.JavaScript.valueToCode(a,"FROM",Blockly.JavaScript.ORDER_COMMA)||"0";a=Blockly.JavaScript.valueToCode(a,"TO",Blockly.JavaScript.ORDER_COMMA)||"0";return[Blockly.JavaScript.provideFunction_("mathRandomInt",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(a, b) {"," if (a > b) {"," // Swap a and b to ensure a is smaller."," var c = a;"," a = b;"," b = c;"," }"," return Math.floor(Math.random() * (b - a + 1) + a);",
"}"])+"("+b+", "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.math_random_float=function(a){return["Math.random()",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.math_atan2=function(a){var b=Blockly.JavaScript.valueToCode(a,"X",Blockly.JavaScript.ORDER_COMMA)||"0";return["Math.atan2("+(Blockly.JavaScript.valueToCode(a,"Y",Blockly.JavaScript.ORDER_COMMA)||"0")+", "+b+") / Math.PI * 180",Blockly.JavaScript.ORDER_DIVISION]};Blockly.JavaScript.procedures={};
Blockly.JavaScript.procedures_defreturn=function(a){var b=Blockly.JavaScript.variableDB_.getName(a.getFieldValue("NAME"),Blockly.PROCEDURE_CATEGORY_NAME),c="";Blockly.JavaScript.STATEMENT_PREFIX&&(c+=Blockly.JavaScript.injectId(Blockly.JavaScript.STATEMENT_PREFIX,a));Blockly.JavaScript.STATEMENT_SUFFIX&&(c+=Blockly.JavaScript.injectId(Blockly.JavaScript.STATEMENT_SUFFIX,a));c&&(c=Blockly.JavaScript.prefixLines(c,Blockly.JavaScript.INDENT));var d="";Blockly.JavaScript.INFINITE_LOOP_TRAP&&(d=Blockly.JavaScript.prefixLines(Blockly.JavaScript.injectId(Blockly.JavaScript.INFINITE_LOOP_TRAP,
a),Blockly.JavaScript.INDENT));var e=Blockly.JavaScript.statementToCode(a,"STACK"),f=Blockly.JavaScript.valueToCode(a,"RETURN",Blockly.JavaScript.ORDER_NONE)||"",g="";e&&f&&(g=c);f&&(f=Blockly.JavaScript.INDENT+"return "+f+";\n");for(var k=[],h=0;h<a.arguments_.length;h++)k[h]=Blockly.JavaScript.variableDB_.getName(a.arguments_[h],Blockly.VARIABLE_CATEGORY_NAME);c="function "+b+"("+k.join(", ")+") {\n"+c+d+e+g+f+"}";c=Blockly.JavaScript.scrub_(a,c);Blockly.JavaScript.definitions_["%"+b]=c;return null};
Blockly.JavaScript.procedures_defnoreturn=Blockly.JavaScript.procedures_defreturn;Blockly.JavaScript.procedures_callreturn=function(a){for(var b=Blockly.JavaScript.variableDB_.getName(a.getFieldValue("NAME"),Blockly.PROCEDURE_CATEGORY_NAME),c=[],d=0;d<a.arguments_.length;d++)c[d]=Blockly.JavaScript.valueToCode(a,"ARG"+d,Blockly.JavaScript.ORDER_COMMA)||"null";return[b+"("+c.join(", ")+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]};
Blockly.JavaScript.procedures_callnoreturn=function(a){return Blockly.JavaScript.procedures_callreturn(a)[0]+";\n"};
Blockly.JavaScript.procedures_ifreturn=function(a){var b="if ("+(Blockly.JavaScript.valueToCode(a,"CONDITION",Blockly.JavaScript.ORDER_NONE)||"false")+") {\n";Blockly.JavaScript.STATEMENT_SUFFIX&&(b+=Blockly.JavaScript.prefixLines(Blockly.JavaScript.injectId(Blockly.JavaScript.STATEMENT_SUFFIX,a),Blockly.JavaScript.INDENT));a.hasReturnValue_?(a=Blockly.JavaScript.valueToCode(a,"VALUE",Blockly.JavaScript.ORDER_NONE)||"null",b+=Blockly.JavaScript.INDENT+"return "+a+";\n"):b+=Blockly.JavaScript.INDENT+
"return;\n";return b+"}\n"};Blockly.JavaScript.texts={};Blockly.JavaScript.text=function(a){return[Blockly.JavaScript.quote_(a.getFieldValue("TEXT")),Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.text_multiline=function(a){a=Blockly.JavaScript.multiline_quote_(a.getFieldValue("TEXT"));a.includes("\n")&&(a="("+a+")");return[a,Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.text.forceString_=function(a){return Blockly.JavaScript.text.forceString_.strRegExp.test(a)?a:"String("+a+")"};
Blockly.JavaScript.text.forceString_.strRegExp=/^\s*'([^']|\\')*'\s*$/;
Blockly.JavaScript.text_join=function(a){switch(a.itemCount_){case 0:return["''",Blockly.JavaScript.ORDER_ATOMIC];case 1:return a=Blockly.JavaScript.valueToCode(a,"ADD0",Blockly.JavaScript.ORDER_NONE)||"''",a=Blockly.JavaScript.text.forceString_(a),[a,Blockly.JavaScript.ORDER_FUNCTION_CALL];case 2:var b=Blockly.JavaScript.valueToCode(a,"ADD0",Blockly.JavaScript.ORDER_NONE)||"''";a=Blockly.JavaScript.valueToCode(a,"ADD1",Blockly.JavaScript.ORDER_NONE)||"''";a=Blockly.JavaScript.text.forceString_(b)+
" + "+Blockly.JavaScript.text.forceString_(a);return[a,Blockly.JavaScript.ORDER_ADDITION];default:b=Array(a.itemCount_);for(var c=0;c<a.itemCount_;c++)b[c]=Blockly.JavaScript.valueToCode(a,"ADD"+c,Blockly.JavaScript.ORDER_COMMA)||"''";a="["+b.join(",")+"].join('')";return[a,Blockly.JavaScript.ORDER_FUNCTION_CALL]}};
Blockly.JavaScript.text_append=function(a){var b=Blockly.JavaScript.variableDB_.getName(a.getFieldValue("VAR"),Blockly.VARIABLE_CATEGORY_NAME);a=Blockly.JavaScript.valueToCode(a,"TEXT",Blockly.JavaScript.ORDER_NONE)||"''";return b+" += "+Blockly.JavaScript.text.forceString_(a)+";\n"};Blockly.JavaScript.text_length=function(a){return[(Blockly.JavaScript.valueToCode(a,"VALUE",Blockly.JavaScript.ORDER_FUNCTION_CALL)||"''")+".length",Blockly.JavaScript.ORDER_MEMBER]};
Blockly.JavaScript.text_isEmpty=function(a){return["!"+(Blockly.JavaScript.valueToCode(a,"VALUE",Blockly.JavaScript.ORDER_MEMBER)||"''")+".length",Blockly.JavaScript.ORDER_LOGICAL_NOT]};
Blockly.JavaScript.text_indexOf=function(a){var b="FIRST"==a.getFieldValue("END")?"indexOf":"lastIndexOf",c=Blockly.JavaScript.valueToCode(a,"FIND",Blockly.JavaScript.ORDER_NONE)||"''";b=(Blockly.JavaScript.valueToCode(a,"VALUE",Blockly.JavaScript.ORDER_MEMBER)||"''")+"."+b+"("+c+")";return a.workspace.options.oneBasedIndex?[b+" + 1",Blockly.JavaScript.ORDER_ADDITION]:[b,Blockly.JavaScript.ORDER_FUNCTION_CALL]};
Blockly.JavaScript.text_charAt=function(a){var b=a.getFieldValue("WHERE")||"FROM_START",c=Blockly.JavaScript.valueToCode(a,"VALUE","RANDOM"==b?Blockly.JavaScript.ORDER_NONE:Blockly.JavaScript.ORDER_MEMBER)||"''";switch(b){case "FIRST":return[c+".charAt(0)",Blockly.JavaScript.ORDER_FUNCTION_CALL];case "LAST":return[c+".slice(-1)",Blockly.JavaScript.ORDER_FUNCTION_CALL];case "FROM_START":return a=Blockly.JavaScript.getAdjusted(a,"AT"),[c+".charAt("+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL];case "FROM_END":return a=
Blockly.JavaScript.getAdjusted(a,"AT",1,!0),[c+".slice("+a+").charAt(0)",Blockly.JavaScript.ORDER_FUNCTION_CALL];case "RANDOM":return[Blockly.JavaScript.provideFunction_("textRandomLetter",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(text) {"," var x = Math.floor(Math.random() * text.length);"," return text[x];","}"])+"("+c+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]}throw Error("Unhandled option (text_charAt).");};
Blockly.JavaScript.text.getIndex_=function(a,b,c){return"FIRST"==b?"0":"FROM_END"==b?a+".length - 1 - "+c:"LAST"==b?a+".length - 1":c};
Blockly.JavaScript.text_getSubstring=function(a){var b=Blockly.JavaScript.valueToCode(a,"STRING",Blockly.JavaScript.ORDER_FUNCTION_CALL)||"''",c=a.getFieldValue("WHERE1"),d=a.getFieldValue("WHERE2");if("FIRST"!=c||"LAST"!=d)if(b.match(/^'?\w+'?$/)||"FROM_END"!=c&&"LAST"!=c&&"FROM_END"!=d&&"LAST"!=d){switch(c){case "FROM_START":var e=Blockly.JavaScript.getAdjusted(a,"AT1");break;case "FROM_END":e=Blockly.JavaScript.getAdjusted(a,"AT1",1,!1,Blockly.JavaScript.ORDER_SUBTRACTION);e=b+".length - "+e;break;
case "FIRST":e="0";break;default:throw Error("Unhandled option (text_getSubstring).");}switch(d){case "FROM_START":a=Blockly.JavaScript.getAdjusted(a,"AT2",1);break;case "FROM_END":a=Blockly.JavaScript.getAdjusted(a,"AT2",0,!1,Blockly.JavaScript.ORDER_SUBTRACTION);a=b+".length - "+a;break;case "LAST":a=b+".length";break;default:throw Error("Unhandled option (text_getSubstring).");}b=b+".slice("+e+", "+a+")"}else{e=Blockly.JavaScript.getAdjusted(a,"AT1");a=Blockly.JavaScript.getAdjusted(a,"AT2");var f=
Blockly.JavaScript.text.getIndex_,g={FIRST:"First",LAST:"Last",FROM_START:"FromStart",FROM_END:"FromEnd"};b=Blockly.JavaScript.provideFunction_("subsequence"+g[c]+g[d],["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(sequence"+("FROM_END"==c||"FROM_START"==c?", at1":"")+("FROM_END"==d||"FROM_START"==d?", at2":"")+") {"," var start = "+f("sequence",c,"at1")+";"," var end = "+f("sequence",d,"at2")+" + 1;"," return sequence.slice(start, end);","}"])+"("+b+("FROM_END"==c||"FROM_START"==
c?", "+e:"")+("FROM_END"==d||"FROM_START"==d?", "+a:"")+")"}return[b,Blockly.JavaScript.ORDER_FUNCTION_CALL]};
Blockly.JavaScript.text_changeCase=function(a){var b={UPPERCASE:".toUpperCase()",LOWERCASE:".toLowerCase()",TITLECASE:null}[a.getFieldValue("CASE")];a=Blockly.JavaScript.valueToCode(a,"TEXT",b?Blockly.JavaScript.ORDER_MEMBER:Blockly.JavaScript.ORDER_NONE)||"''";return[b?a+b:Blockly.JavaScript.provideFunction_("textToTitleCase",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(str) {"," return str.replace(/\\S+/g,"," function(txt) {return txt[0].toUpperCase() + txt.substring(1).toLowerCase();});",
"}"])+"("+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.text_trim=function(a){var b={LEFT:".replace(/^[\\s\\xa0]+/, '')",RIGHT:".replace(/[\\s\\xa0]+$/, '')",BOTH:".trim()"}[a.getFieldValue("MODE")];return[(Blockly.JavaScript.valueToCode(a,"TEXT",Blockly.JavaScript.ORDER_MEMBER)||"''")+b,Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.text_print=function(a){return"window.alert("+(Blockly.JavaScript.valueToCode(a,"TEXT",Blockly.JavaScript.ORDER_NONE)||"''")+");\n"};
Blockly.JavaScript.text_prompt_ext=function(a){var b="window.prompt("+(a.getField("TEXT")?Blockly.JavaScript.quote_(a.getFieldValue("TEXT")):Blockly.JavaScript.valueToCode(a,"TEXT",Blockly.JavaScript.ORDER_NONE)||"''")+")";"NUMBER"==a.getFieldValue("TYPE")&&(b="Number("+b+")");return[b,Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.text_prompt=Blockly.JavaScript.text_prompt_ext;
Blockly.JavaScript.text_count=function(a){var b=Blockly.JavaScript.valueToCode(a,"TEXT",Blockly.JavaScript.ORDER_MEMBER)||"''";a=Blockly.JavaScript.valueToCode(a,"SUB",Blockly.JavaScript.ORDER_NONE)||"''";return[Blockly.JavaScript.provideFunction_("textCount",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(haystack, needle) {"," if (needle.length === 0) {"," return haystack.length + 1;"," } else {"," return haystack.split(needle).length - 1;"," }","}"])+"("+b+", "+a+")",Blockly.JavaScript.ORDER_SUBTRACTION]};
Blockly.JavaScript.text_replace=function(a){var b=Blockly.JavaScript.valueToCode(a,"TEXT",Blockly.JavaScript.ORDER_MEMBER)||"''",c=Blockly.JavaScript.valueToCode(a,"FROM",Blockly.JavaScript.ORDER_NONE)||"''";a=Blockly.JavaScript.valueToCode(a,"TO",Blockly.JavaScript.ORDER_NONE)||"''";return[Blockly.JavaScript.provideFunction_("textReplace",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(haystack, needle, replacement) {",' needle = needle.replace(/([-()\\[\\]{}+?*.$\\^|,:#<!\\\\])/g,"\\\\$1")',
' .replace(/\\x08/g,"\\\\x08");'," return haystack.replace(new RegExp(needle, 'g'), replacement);","}"])+"("+b+", "+c+", "+a+")",Blockly.JavaScript.ORDER_MEMBER]};Blockly.JavaScript.text_reverse=function(a){return[(Blockly.JavaScript.valueToCode(a,"TEXT",Blockly.JavaScript.ORDER_MEMBER)||"''")+".split('').reverse().join('')",Blockly.JavaScript.ORDER_MEMBER]};Blockly.JavaScript.variables={};Blockly.JavaScript.variables_get=function(a){return[Blockly.JavaScript.variableDB_.getName(a.getFieldValue("VAR"),Blockly.VARIABLE_CATEGORY_NAME),Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.variables_set=function(a){var b=Blockly.JavaScript.valueToCode(a,"VALUE",Blockly.JavaScript.ORDER_ASSIGNMENT)||"0";return Blockly.JavaScript.variableDB_.getName(a.getFieldValue("VAR"),Blockly.VARIABLE_CATEGORY_NAME)+" = "+b+";\n"};Blockly.JavaScript.variablesDynamic={};Blockly.JavaScript.variables_get_dynamic=Blockly.JavaScript.variables_get;Blockly.JavaScript.variables_set_dynamic=Blockly.JavaScript.variables_set;

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="12.71" height="8.79" viewBox="0 0 12.71 8.79"><title>dropdown-arrow</title><g opacity="0.1"><path d="M12.71,2.44A2.41,2.41,0,0,1,12,4.16L8.08,8.08a2.45,2.45,0,0,1-3.45,0L0.72,4.16A2.42,2.42,0,0,1,0,2.44,2.48,2.48,0,0,1,.71.71C1,0.47,1.43,0,6.36,0S11.75,0.46,12,.71A2.44,2.44,0,0,1,12.71,2.44Z" fill="#231f20"/></g><path d="M6.36,7.79a1.43,1.43,0,0,1-1-.42L1.42,3.45a1.44,1.44,0,0,1,0-2c0.56-.56,9.31-0.56,9.87,0a1.44,1.44,0,0,1,0,2L7.37,7.37A1.43,1.43,0,0,1,6.36,7.79Z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 569 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1010 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 771 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 738 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="96px" height="124px">
<style type="text/css">
#background {
fill: none;
}
.arrows {
fill: #000;
stroke: none;
}
.selected>.arrows {
fill: #fff;
}
.checkmark {
fill: #000;
font-family: sans-serif;
font-size: 10pt;
text-anchor: middle;
}
.trash {
fill: #888;
}
.zoom {
fill: none;
stroke: #888;
stroke-width: 2;
stroke-linecap: round;
}
.zoom>.center {
fill: #888;
stroke-width: 0;
}
</style>
<rect id="background" width="96" height="124" x="0" y="0" />
<g>
<path class="arrows" d="M 13,1.5 13,14.5 1.74,8 z" />
<path class="arrows" d="M 17.5,3 30.5,3 24,14.26 z" />
<path class="arrows" d="M 35,1.5 35,14.5 46.26,8 z" />
</g>
<g class="selected" transform="translate(0, 16)">
<path class="arrows" d="M 13,1.5 13,14.5 1.74,8 z" />
<path class="arrows" d="M 17.5,3 30.5,3 24,14.26 z" />
<path class="arrows" d="M 35,1.5 35,14.5 46.26,8 z" />
</g>
<text class="checkmark" x="55.5" y="28">&#10003;</text>
<g class="trash">
<path d="M 2,41 v 6 h 42 v -6 h -10.5 l -3,-3 h -15 l -3,3 z" />
<rect width="36" height="20" x="5" y="50" />
<rect width="36" height="42" x="5" y="50" rx="4" ry="4" />
</g>
<g class="zoom">
<circle r="11.5" cx="16" cy="108" />
<circle r="4.3" cx="16" cy="108" class="center" />
<path d="m 28,108 h3" />
<path d="m 1,108 h3" />
<path d="m 16,120 v3" />
<path d="m 16,93 v3" />
</g>
<g class="zoom">
<circle r="15" cx="48" cy="108" />
<path d="m 48,101.6 v12.8" />
<path d="m 41.6,108 h12.8" />
</g>
<g class="zoom">
<circle r="15" cx="80" cy="108" />
<path d="m 73.6,108 h12.8" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

434
_server/blockly/zh-hans.js Normal file
View File

@ -0,0 +1,434 @@
// This file was automatically generated. Do not modify.
'use strict';
Blockly.Msg["ADD_COMMENT"] = "添加注释";
Blockly.Msg["CANNOT_DELETE_VARIABLE_PROCEDURE"] = "不能删除变量“%1”因为它是函数“%2”定义的一部分";
Blockly.Msg["CHANGE_VALUE_TITLE"] = "更改值:";
Blockly.Msg["CLEAN_UP"] = "整理块";
Blockly.Msg["COLLAPSED_WARNINGS_WARNING"] = "已收起的信息块内包含警告。";
Blockly.Msg["COLLAPSE_ALL"] = "折叠块";
Blockly.Msg["COLLAPSE_BLOCK"] = "折叠块";
Blockly.Msg["COLOUR_BLEND_COLOUR1"] = "颜色1";
Blockly.Msg["COLOUR_BLEND_COLOUR2"] = "颜色2";
Blockly.Msg["COLOUR_BLEND_HELPURL"] = "https://meyerweb.com/eric/tools/color-blend/#:::rgbp"; // untranslated
Blockly.Msg["COLOUR_BLEND_RATIO"] = "比例";
Blockly.Msg["COLOUR_BLEND_TITLE"] = "混合";
Blockly.Msg["COLOUR_BLEND_TOOLTIP"] = "把两种颜色以一个给定的比例(0.0-1.0)进行混合。";
Blockly.Msg["COLOUR_PICKER_HELPURL"] = "https://zh.wikipedia.org/wiki/颜色";
Blockly.Msg["COLOUR_PICKER_TOOLTIP"] = "从调色板中选择一种颜色。";
Blockly.Msg["COLOUR_RANDOM_HELPURL"] = "http://randomcolour.com"; // untranslated
Blockly.Msg["COLOUR_RANDOM_TITLE"] = "随机颜色";
Blockly.Msg["COLOUR_RANDOM_TOOLTIP"] = "随机选择一种颜色。";
Blockly.Msg["COLOUR_RGB_BLUE"] = "蓝色";
Blockly.Msg["COLOUR_RGB_GREEN"] = "绿色";
Blockly.Msg["COLOUR_RGB_HELPURL"] = "https://www.december.com/html/spec/colorpercompact.html"; // untranslated
Blockly.Msg["COLOUR_RGB_RED"] = "红色";
Blockly.Msg["COLOUR_RGB_TITLE"] = "颜色";
Blockly.Msg["COLOUR_RGB_TOOLTIP"] = "通过指定红色、绿色和蓝色的量创建一种颜色。所有的值必须在0和100之间。";
Blockly.Msg["CONTROLS_FLOW_STATEMENTS_HELPURL"] = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated
Blockly.Msg["CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK"] = "跳出循环";
Blockly.Msg["CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE"] = "继续下一轮循环";
Blockly.Msg["CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK"] = "跳出包含它的循环。";
Blockly.Msg["CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE"] = "跳过本轮循环的剩余部分,并继进行续下一轮迭代。";
Blockly.Msg["CONTROLS_FLOW_STATEMENTS_WARNING"] = "警告:这个块只能在循环内使用。";
Blockly.Msg["CONTROLS_FOREACH_HELPURL"] = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated
Blockly.Msg["CONTROLS_FOREACH_TITLE"] = "为列表 %2 里的每一项 %1";
Blockly.Msg["CONTROLS_FOREACH_TOOLTIP"] = "遍历列表中的每一项,将变量“%1”设为所选项并执行一些语句。";
Blockly.Msg["CONTROLS_FOR_HELPURL"] = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated
Blockly.Msg["CONTROLS_FOR_TITLE"] = "变量 %1 从 %2 数到 %3 每次增加 %4";
Blockly.Msg["CONTROLS_FOR_TOOLTIP"] = "用变量%1记录从开始数值到终止数值之间的数值数值按指定间隔增加并执行指定的块。";
Blockly.Msg["CONTROLS_IF_ELSEIF_TOOLTIP"] = "在这个if语句块中增加一个条件。";
Blockly.Msg["CONTROLS_IF_ELSE_TOOLTIP"] = "在这个if语句块中添加一个最终的包括所有其余情况的条件。";
Blockly.Msg["CONTROLS_IF_HELPURL"] = "https://github.com/google/blockly/wiki/IfElse"; // untranslated
Blockly.Msg["CONTROLS_IF_IF_TOOLTIP"] = "增加、删除或重新排列各节来重新配置这个if语句块。";
Blockly.Msg["CONTROLS_IF_MSG_ELSE"] = "否则";
Blockly.Msg["CONTROLS_IF_MSG_ELSEIF"] = "否则如果";
Blockly.Msg["CONTROLS_IF_MSG_IF"] = "如果";
Blockly.Msg["CONTROLS_IF_TOOLTIP_1"] = "如果值为真,执行一些语句。";
Blockly.Msg["CONTROLS_IF_TOOLTIP_2"] = "如果值为真,则执行第一块语句。否则,则执行第二块语句。";
Blockly.Msg["CONTROLS_IF_TOOLTIP_3"] = "如果第一个值为真,则执行第一块的语句。否则,如果第二个值为真,则执行第二块的语句。";
Blockly.Msg["CONTROLS_IF_TOOLTIP_4"] = "如果第一个值为真,则执行第一块对语句。否则,如果第二个值为真,则执行语句的第二块。如果没有值为真,则执行最后一块的语句。";
Blockly.Msg["CONTROLS_REPEAT_HELPURL"] = "https://zh.wikipedia.org/wiki/For循环";
Blockly.Msg["CONTROLS_REPEAT_INPUT_DO"] = "执行";
Blockly.Msg["CONTROLS_REPEAT_TITLE"] = "重复 %1 次";
Blockly.Msg["CONTROLS_REPEAT_TOOLTIP"] = "多次执行一些语句。";
Blockly.Msg["CONTROLS_WHILEUNTIL_HELPURL"] = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated
Blockly.Msg["CONTROLS_WHILEUNTIL_OPERATOR_UNTIL"] = "重复直到条件满足";
Blockly.Msg["CONTROLS_WHILEUNTIL_OPERATOR_WHILE"] = "当条件满足时重复";
Blockly.Msg["CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL"] = "只要值为假,执行一些语句。";
Blockly.Msg["CONTROLS_WHILEUNTIL_TOOLTIP_WHILE"] = "只要值为真,执行一些语句。";
Blockly.Msg["DELETE_ALL_BLOCKS"] = "删除所有 %1 个块吗?";
Blockly.Msg["DELETE_BLOCK"] = "删除块";
Blockly.Msg["DELETE_VARIABLE"] = "删除变量“%1”";
Blockly.Msg["DELETE_VARIABLE_CONFIRMATION"] = "要删除对变量“%2”的%1个引用吗";
Blockly.Msg["DELETE_X_BLOCKS"] = "删除 %1 个块";
Blockly.Msg["DISABLE_BLOCK"] = "禁用块";
Blockly.Msg["DUPLICATE_BLOCK"] = "复制";
Blockly.Msg["DUPLICATE_COMMENT"] = "复制注释";
Blockly.Msg["ENABLE_BLOCK"] = "启用块";
Blockly.Msg["EXPAND_ALL"] = "展开块";
Blockly.Msg["EXPAND_BLOCK"] = "展开块";
Blockly.Msg["EXTERNAL_INPUTS"] = "外部输入";
Blockly.Msg["HELP"] = "帮助";
Blockly.Msg["INLINE_INPUTS"] = "单行输入";
Blockly.Msg["IOS_CANCEL"] = "取消";
Blockly.Msg["IOS_ERROR"] = "错误";
Blockly.Msg["IOS_OK"] = "确定";
Blockly.Msg["IOS_PROCEDURES_ADD_INPUT"] = "+添加输入";
Blockly.Msg["IOS_PROCEDURES_ALLOW_STATEMENTS"] = "允许的语句";
Blockly.Msg["IOS_PROCEDURES_DUPLICATE_INPUTS_ERROR"] = "这个函数有多个输入。";
Blockly.Msg["IOS_PROCEDURES_INPUTS"] = "输入";
Blockly.Msg["IOS_VARIABLES_ADD_BUTTON"] = "添加";
Blockly.Msg["IOS_VARIABLES_ADD_VARIABLE"] = "+添加变量";
Blockly.Msg["IOS_VARIABLES_DELETE_BUTTON"] = "删除";
Blockly.Msg["IOS_VARIABLES_EMPTY_NAME_ERROR"] = "你不能使用空白的变量名。";
Blockly.Msg["IOS_VARIABLES_RENAME_BUTTON"] = "重命名";
Blockly.Msg["IOS_VARIABLES_VARIABLE_NAME"] = "变量名";
Blockly.Msg["LISTS_CREATE_EMPTY_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#create-empty-list";
Blockly.Msg["LISTS_CREATE_EMPTY_TITLE"] = "创建空列表";
Blockly.Msg["LISTS_CREATE_EMPTY_TOOLTIP"] = "返回一个列表,长度为 0不包含任何数据记录";
Blockly.Msg["LISTS_CREATE_WITH_CONTAINER_TITLE_ADD"] = "列表";
Blockly.Msg["LISTS_CREATE_WITH_CONTAINER_TOOLTIP"] = "增加、删除或重新排列各部分以此重新配置这个列表块。";
Blockly.Msg["LISTS_CREATE_WITH_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#create-list-with";
Blockly.Msg["LISTS_CREATE_WITH_INPUT_WITH"] = "建立列表从";
Blockly.Msg["LISTS_CREATE_WITH_ITEM_TOOLTIP"] = "将一个项添加到列表中。";
Blockly.Msg["LISTS_CREATE_WITH_TOOLTIP"] = "建立一个具有任意数量项目的列表。";
Blockly.Msg["LISTS_GET_INDEX_FIRST"] = "第一个";
Blockly.Msg["LISTS_GET_INDEX_FROM_END"] = "倒数第#";
Blockly.Msg["LISTS_GET_INDEX_FROM_START"] = "#";
Blockly.Msg["LISTS_GET_INDEX_GET"] = "取得";
Blockly.Msg["LISTS_GET_INDEX_GET_REMOVE"] = "取得并移除";
Blockly.Msg["LISTS_GET_INDEX_LAST"] = "最后一个";
Blockly.Msg["LISTS_GET_INDEX_RANDOM"] = "随机的";
Blockly.Msg["LISTS_GET_INDEX_REMOVE"] = "移除";
Blockly.Msg["LISTS_GET_INDEX_TAIL"] = "-";
Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_FIRST"] = "返回列表中的第一项。";
Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_FROM"] = "返回在列表中的指定位置的项。";
Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_LAST"] = "返回列表中的最后一项。";
Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_RANDOM"] = "返回列表中的随机一项。";
Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST"] = "移除并返回列表中的第一项。";
Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM"] = "移除并返回列表中的指定位置的项。";
Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST"] = "移除并返回列表中的最后一项。";
Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM"] = "移除并返回列表中的随机一项。";
Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST"] = "移除列表中的第一项";
Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM"] = "移除在列表中的指定位置的项。";
Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST"] = "移除列表中的最后一项";
Blockly.Msg["LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM"] = "删除列表中的随机一项。";
Blockly.Msg["LISTS_GET_SUBLIST_END_FROM_END"] = "到倒数第#";
Blockly.Msg["LISTS_GET_SUBLIST_END_FROM_START"] = "到#";
Blockly.Msg["LISTS_GET_SUBLIST_END_LAST"] = "到最后";
Blockly.Msg["LISTS_GET_SUBLIST_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated
Blockly.Msg["LISTS_GET_SUBLIST_START_FIRST"] = "获取子列表从第一个";
Blockly.Msg["LISTS_GET_SUBLIST_START_FROM_END"] = "获取子列表从最后一个#";
Blockly.Msg["LISTS_GET_SUBLIST_START_FROM_START"] = "获取子列表从#";
Blockly.Msg["LISTS_GET_SUBLIST_TAIL"] = "-";
Blockly.Msg["LISTS_GET_SUBLIST_TOOLTIP"] = "复制列表中指定的部分。";
Blockly.Msg["LISTS_INDEX_FROM_END_TOOLTIP"] = "%1是最后一项。";
Blockly.Msg["LISTS_INDEX_FROM_START_TOOLTIP"] = "%1是第一项。";
Blockly.Msg["LISTS_INDEX_OF_FIRST"] = "寻找第一次出现的项";
Blockly.Msg["LISTS_INDEX_OF_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated
Blockly.Msg["LISTS_INDEX_OF_LAST"] = "寻找最后一次出现的项";
Blockly.Msg["LISTS_INDEX_OF_TOOLTIP"] = "返回在列表中的第一/最后一个匹配项的索引值。如果找不到项目则返回%1。";
Blockly.Msg["LISTS_INLIST"] = "在列表中";
Blockly.Msg["LISTS_ISEMPTY_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated
Blockly.Msg["LISTS_ISEMPTY_TITLE"] = "%1是空的";
Blockly.Msg["LISTS_ISEMPTY_TOOLTIP"] = "如果改列表为空,则返回真。";
Blockly.Msg["LISTS_LENGTH_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated
Blockly.Msg["LISTS_LENGTH_TITLE"] = "%1的长度";
Blockly.Msg["LISTS_LENGTH_TOOLTIP"] = "返回列表的长度。";
Blockly.Msg["LISTS_REPEAT_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated
Blockly.Msg["LISTS_REPEAT_TITLE"] = "建立列表使用项 %1 重复 %2 次";
Blockly.Msg["LISTS_REPEAT_TOOLTIP"] = "建立包含指定重复次数的值的列表。";
Blockly.Msg["LISTS_REVERSE_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#reversing-a-list";
Blockly.Msg["LISTS_REVERSE_MESSAGE0"] = "倒转%1";
Blockly.Msg["LISTS_REVERSE_TOOLTIP"] = "倒转一个列表的拷贝。";
Blockly.Msg["LISTS_SET_INDEX_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated
Blockly.Msg["LISTS_SET_INDEX_INPUT_TO"] = "值为";
Blockly.Msg["LISTS_SET_INDEX_INSERT"] = "插入在";
Blockly.Msg["LISTS_SET_INDEX_SET"] = "设置";
Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST"] = "在列表的起始处添加该项。";
Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_INSERT_FROM"] = "插入在列表中指定位置的项。";
Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_INSERT_LAST"] = "在列表的末尾处添加该项。";
Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM"] = "在列表的随机位置插入该项。";
Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_SET_FIRST"] = "设置列表中的第一项。";
Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_SET_FROM"] = "设置在列表中指定位置的项。";
Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_SET_LAST"] = "设置列表中的最后一项。";
Blockly.Msg["LISTS_SET_INDEX_TOOLTIP_SET_RANDOM"] = "设置列表中的随机一项。";
Blockly.Msg["LISTS_SORT_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#sorting-a-list";
Blockly.Msg["LISTS_SORT_ORDER_ASCENDING"] = "升序";
Blockly.Msg["LISTS_SORT_ORDER_DESCENDING"] = "降序";
Blockly.Msg["LISTS_SORT_TITLE"] = "排序%1 %2 %3";
Blockly.Msg["LISTS_SORT_TOOLTIP"] = "排序一个列表的拷贝。";
Blockly.Msg["LISTS_SORT_TYPE_IGNORECASE"] = "按字母排序,忽略大小写";
Blockly.Msg["LISTS_SORT_TYPE_NUMERIC"] = "按数字排序";
Blockly.Msg["LISTS_SORT_TYPE_TEXT"] = "按字母排序";
Blockly.Msg["LISTS_SPLIT_HELPURL"] = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists";
Blockly.Msg["LISTS_SPLIT_LIST_FROM_TEXT"] = "从文本制作列表";
Blockly.Msg["LISTS_SPLIT_TEXT_FROM_LIST"] = "从列表拆出文本";
Blockly.Msg["LISTS_SPLIT_TOOLTIP_JOIN"] = "加入文本列表至一个文本,由分隔符分隔。";
Blockly.Msg["LISTS_SPLIT_TOOLTIP_SPLIT"] = "拆分文本到文本列表,按每个分隔符拆分。";
Blockly.Msg["LISTS_SPLIT_WITH_DELIMITER"] = "用分隔符";
Blockly.Msg["LOGIC_BOOLEAN_FALSE"] = "假";
Blockly.Msg["LOGIC_BOOLEAN_HELPURL"] = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated
Blockly.Msg["LOGIC_BOOLEAN_TOOLTIP"] = "返回真或假。";
Blockly.Msg["LOGIC_BOOLEAN_TRUE"] = "真";
Blockly.Msg["LOGIC_COMPARE_HELPURL"] = "https://zh.wikipedia.org/wiki/不等";
Blockly.Msg["LOGIC_COMPARE_TOOLTIP_EQ"] = "如果两个输入结果相等,则返回真。";
Blockly.Msg["LOGIC_COMPARE_TOOLTIP_GT"] = "如果第一个输入结果比第二个大,则返回真。";
Blockly.Msg["LOGIC_COMPARE_TOOLTIP_GTE"] = "如果第一个输入结果大于或等于第二个输入结果,则返回真。";
Blockly.Msg["LOGIC_COMPARE_TOOLTIP_LT"] = "如果第一个输入结果比第二个小,则返回真。";
Blockly.Msg["LOGIC_COMPARE_TOOLTIP_LTE"] = "如果第一个输入结果小于或等于第二个输入结果,则返回真。";
Blockly.Msg["LOGIC_COMPARE_TOOLTIP_NEQ"] = "如果两个输入结果不相等,则返回真。";
Blockly.Msg["LOGIC_NEGATE_HELPURL"] = "https://github.com/google/blockly/wiki/Logic#not";
Blockly.Msg["LOGIC_NEGATE_TITLE"] = "非%1";
Blockly.Msg["LOGIC_NEGATE_TOOLTIP"] = "如果输入结果为假,则返回真;如果输入结果为真,则返回假。";
Blockly.Msg["LOGIC_NULL"] = "空";
Blockly.Msg["LOGIC_NULL_HELPURL"] = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated
Blockly.Msg["LOGIC_NULL_TOOLTIP"] = "返回空值。";
Blockly.Msg["LOGIC_OPERATION_AND"] = "并且";
Blockly.Msg["LOGIC_OPERATION_HELPURL"] = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated
Blockly.Msg["LOGIC_OPERATION_OR"] = "或";
Blockly.Msg["LOGIC_OPERATION_TOOLTIP_AND"] = "如果两个输入结果都为真,则返回真。";
Blockly.Msg["LOGIC_OPERATION_TOOLTIP_OR"] = "如果至少有一个输入结果为真,则返回真。";
Blockly.Msg["LOGIC_TERNARY_CONDITION"] = "断言";
Blockly.Msg["LOGIC_TERNARY_HELPURL"] = "https://zh.wikipedia.org/wiki/条件运算符";
Blockly.Msg["LOGIC_TERNARY_IF_FALSE"] = "如果为假";
Blockly.Msg["LOGIC_TERNARY_IF_TRUE"] = "如果为真";
Blockly.Msg["LOGIC_TERNARY_TOOLTIP"] = "检查“断言”里的条件语句。如果条件为真,则返回“如果为真”的值,否则,则返回“如果为假”的值。";
Blockly.Msg["MATH_ADDITION_SYMBOL"] = "+"; // untranslated
Blockly.Msg["MATH_ARITHMETIC_HELPURL"] = "https://zh.wikipedia.org/wiki/算术";
Blockly.Msg["MATH_ARITHMETIC_TOOLTIP_ADD"] = "返回两个数值的和。";
Blockly.Msg["MATH_ARITHMETIC_TOOLTIP_DIVIDE"] = "返回两个数值的商。";
Blockly.Msg["MATH_ARITHMETIC_TOOLTIP_MINUS"] = "返回两个数值的差值。";
Blockly.Msg["MATH_ARITHMETIC_TOOLTIP_MULTIPLY"] = "返回两个数值的乘积。";
Blockly.Msg["MATH_ARITHMETIC_TOOLTIP_POWER"] = "返回以第一个数值为底数,以第二个数值为幂的结果。";
Blockly.Msg["MATH_ATAN2_HELPURL"] = "https://zh.wikipedia.org/wiki/反正切2";
Blockly.Msg["MATH_ATAN2_TITLE"] = "点(x:%1,y:%2)的方位角";
Blockly.Msg["MATH_ATAN2_TOOLTIP"] = "返回点XY的反正切值范围为-180到180度。";
Blockly.Msg["MATH_CHANGE_HELPURL"] = "https://zh.wikipedia.org/wiki/加法";
Blockly.Msg["MATH_CHANGE_TITLE"] = "将 %1 增加 %2";
Blockly.Msg["MATH_CHANGE_TOOLTIP"] = "为变量“%1”增加一个数值。";
Blockly.Msg["MATH_CONSTANT_HELPURL"] = "https://zh.wikipedia.org/wiki/数学常数";
Blockly.Msg["MATH_CONSTANT_TOOLTIP"] = "返回一个常见常量:π (3.141…)、e (2.718…)、φ (1.618…)、平方根 (1.414…)、开平方根 (0.707…)或∞ (无限大)。";
Blockly.Msg["MATH_CONSTRAIN_HELPURL"] = "https://en.wikipedia.org/wiki/Clamping_(graphics)"; // untranslated
Blockly.Msg["MATH_CONSTRAIN_TITLE"] = "将 %1 限制在 最低 %2 到最高 %3 之间";
Blockly.Msg["MATH_CONSTRAIN_TOOLTIP"] = "将一个数值限制在两个指定的数值范围(含边界)之间。";
Blockly.Msg["MATH_DIVISION_SYMBOL"] = "÷"; // untranslated
Blockly.Msg["MATH_IS_DIVISIBLE_BY"] = "可被整除";
Blockly.Msg["MATH_IS_EVEN"] = "是偶数";
Blockly.Msg["MATH_IS_NEGATIVE"] = "是负数";
Blockly.Msg["MATH_IS_ODD"] = "是奇数";
Blockly.Msg["MATH_IS_POSITIVE"] = "是正数";
Blockly.Msg["MATH_IS_PRIME"] = "是质数";
Blockly.Msg["MATH_IS_TOOLTIP"] = "检查一个数值是否是偶数、奇数、质数、自然数、正数、负数或者是否能被某数整除。返回真或假。";
Blockly.Msg["MATH_IS_WHOLE"] = "是整数";
Blockly.Msg["MATH_MODULO_HELPURL"] = "https://zh.wikipedia.org/wiki/模除";
Blockly.Msg["MATH_MODULO_TITLE"] = "取 %1 ÷ %2 的余数";
Blockly.Msg["MATH_MODULO_TOOLTIP"] = "返回这两个数字相除后的余数。";
Blockly.Msg["MATH_MULTIPLICATION_SYMBOL"] = "×"; // untranslated
Blockly.Msg["MATH_NUMBER_HELPURL"] = "https://zh.wikipedia.org/wiki/数";
Blockly.Msg["MATH_NUMBER_TOOLTIP"] = "一个数值。";
Blockly.Msg["MATH_ONLIST_HELPURL"] = ""; // untranslated
Blockly.Msg["MATH_ONLIST_OPERATOR_AVERAGE"] = "列表平均值";
Blockly.Msg["MATH_ONLIST_OPERATOR_MAX"] = "列表最大值";
Blockly.Msg["MATH_ONLIST_OPERATOR_MEDIAN"] = "列表中位数";
Blockly.Msg["MATH_ONLIST_OPERATOR_MIN"] = "列表最小值";
Blockly.Msg["MATH_ONLIST_OPERATOR_MODE"] = "列表中的众数";
Blockly.Msg["MATH_ONLIST_OPERATOR_RANDOM"] = "列表随机项";
Blockly.Msg["MATH_ONLIST_OPERATOR_STD_DEV"] = "列表的标准差";
Blockly.Msg["MATH_ONLIST_OPERATOR_SUM"] = "列表中数值的和";
Blockly.Msg["MATH_ONLIST_TOOLTIP_AVERAGE"] = "返回列表中的数值的平均值。";
Blockly.Msg["MATH_ONLIST_TOOLTIP_MAX"] = "返回列表中最大值。";
Blockly.Msg["MATH_ONLIST_TOOLTIP_MEDIAN"] = "返回列表中数值的中位数。";
Blockly.Msg["MATH_ONLIST_TOOLTIP_MIN"] = "返回列表中最小值。";
Blockly.Msg["MATH_ONLIST_TOOLTIP_MODE"] = "返回列表中的出现次数最多的项的列表。";
Blockly.Msg["MATH_ONLIST_TOOLTIP_RANDOM"] = "从列表中返回一个随机的元素。";
Blockly.Msg["MATH_ONLIST_TOOLTIP_STD_DEV"] = "返回列表的标准差。";
Blockly.Msg["MATH_ONLIST_TOOLTIP_SUM"] = "返回列表中的所有数值的和。";
Blockly.Msg["MATH_POWER_SYMBOL"] = "^"; // untranslated
Blockly.Msg["MATH_RANDOM_FLOAT_HELPURL"] = "https://zh.wikipedia.org/wiki/随机数生成器";
Blockly.Msg["MATH_RANDOM_FLOAT_TITLE_RANDOM"] = "随机小数";
Blockly.Msg["MATH_RANDOM_FLOAT_TOOLTIP"] = "返回一个介于0.0到1.0之间(含边界)的随机数。";
Blockly.Msg["MATH_RANDOM_INT_HELPURL"] = "https://zh.wikipedia.org/wiki/随机数生成器";
Blockly.Msg["MATH_RANDOM_INT_TITLE"] = "从 %1 到 %2 范围内的随机整数";
Blockly.Msg["MATH_RANDOM_INT_TOOLTIP"] = "返回一个限制在两个指定数值的范围(含边界)之间的随机整数。";
Blockly.Msg["MATH_ROUND_HELPURL"] = "https://zh.wikipedia.org/wiki/数值修约";
Blockly.Msg["MATH_ROUND_OPERATOR_ROUND"] = "四舍五入";
Blockly.Msg["MATH_ROUND_OPERATOR_ROUNDDOWN"] = "向下舍入";
Blockly.Msg["MATH_ROUND_OPERATOR_ROUNDUP"] = "向上舍入";
Blockly.Msg["MATH_ROUND_TOOLTIP"] = "数字向上或向下舍入。";
Blockly.Msg["MATH_SINGLE_HELPURL"] = "https://zh.wikipedia.org/wiki/平方根";
Blockly.Msg["MATH_SINGLE_OP_ABSOLUTE"] = "绝对值";
Blockly.Msg["MATH_SINGLE_OP_ROOT"] = "平方根";
Blockly.Msg["MATH_SINGLE_TOOLTIP_ABS"] = "返回一个数值的绝对值。";
Blockly.Msg["MATH_SINGLE_TOOLTIP_EXP"] = "返回一个数值的e次幂。";
Blockly.Msg["MATH_SINGLE_TOOLTIP_LN"] = "返回一个数值的自然对数。";
Blockly.Msg["MATH_SINGLE_TOOLTIP_LOG10"] = "返回一个数值的以10为底的对数。";
Blockly.Msg["MATH_SINGLE_TOOLTIP_NEG"] = "返回一个数值的相反数。";
Blockly.Msg["MATH_SINGLE_TOOLTIP_POW10"] = "返回一个数值的10次幂。";
Blockly.Msg["MATH_SINGLE_TOOLTIP_ROOT"] = "返回一个数的平方根。";
Blockly.Msg["MATH_SUBTRACTION_SYMBOL"] = "-"; // untranslated
Blockly.Msg["MATH_TRIG_ACOS"] = "acos"; // untranslated
Blockly.Msg["MATH_TRIG_ASIN"] = "asin"; // untranslated
Blockly.Msg["MATH_TRIG_ATAN"] = "atan"; // untranslated
Blockly.Msg["MATH_TRIG_COS"] = "cos"; // untranslated
Blockly.Msg["MATH_TRIG_HELPURL"] = "https://zh.wikipedia.org/wiki/三角函数";
Blockly.Msg["MATH_TRIG_SIN"] = "sin"; // untranslated
Blockly.Msg["MATH_TRIG_TAN"] = "tan"; // untranslated
Blockly.Msg["MATH_TRIG_TOOLTIP_ACOS"] = "返回一个数值的反余弦值。";
Blockly.Msg["MATH_TRIG_TOOLTIP_ASIN"] = "返回一个数值的反正弦值。";
Blockly.Msg["MATH_TRIG_TOOLTIP_ATAN"] = "返回一个数值的反正切值。";
Blockly.Msg["MATH_TRIG_TOOLTIP_COS"] = "返回指定角度的余弦值(非弧度)。";
Blockly.Msg["MATH_TRIG_TOOLTIP_SIN"] = "返回指定角度的正弦值(非弧度)。";
Blockly.Msg["MATH_TRIG_TOOLTIP_TAN"] = "返回指定角度的正切值(非弧度)。";
Blockly.Msg["NEW_COLOUR_VARIABLE"] = "创建颜色变量...";
Blockly.Msg["NEW_NUMBER_VARIABLE"] = "创建数字变量...";
Blockly.Msg["NEW_STRING_VARIABLE"] = "创建字符串变量...";
Blockly.Msg["NEW_VARIABLE"] = "创建变量...";
Blockly.Msg["NEW_VARIABLE_TITLE"] = "新变量的名称:";
Blockly.Msg["NEW_VARIABLE_TYPE_TITLE"] = "新变量的类型:";
Blockly.Msg["ORDINAL_NUMBER_SUFFIX"] = "-";
Blockly.Msg["PROCEDURES_ALLOW_STATEMENTS"] = "允许声明";
Blockly.Msg["PROCEDURES_BEFORE_PARAMS"] = "与:";
Blockly.Msg["PROCEDURES_CALLNORETURN_HELPURL"] = "https://zh.wikipedia.org/wiki/子程序";
Blockly.Msg["PROCEDURES_CALLNORETURN_TOOLTIP"] = "运行用户定义的函数“%1”。";
Blockly.Msg["PROCEDURES_CALLRETURN_HELPURL"] = "https://zh.wikipedia.org/wiki/子程序";
Blockly.Msg["PROCEDURES_CALLRETURN_TOOLTIP"] = "运行用户定义的函数“%1”并使用它的输出值。";
Blockly.Msg["PROCEDURES_CALL_BEFORE_PARAMS"] = "与:";
Blockly.Msg["PROCEDURES_CREATE_DO"] = "创建“%1”";
Blockly.Msg["PROCEDURES_DEFNORETURN_COMMENT"] = "描述该功能...";
Blockly.Msg["PROCEDURES_DEFNORETURN_DO"] = "-";
Blockly.Msg["PROCEDURES_DEFNORETURN_HELPURL"] = "https://zh.wikipedia.org/wiki/子程序";
Blockly.Msg["PROCEDURES_DEFNORETURN_PROCEDURE"] = "做点什么";
Blockly.Msg["PROCEDURES_DEFNORETURN_TITLE"] = "至";
Blockly.Msg["PROCEDURES_DEFNORETURN_TOOLTIP"] = "创建一个不带输出值的函数。";
Blockly.Msg["PROCEDURES_DEFRETURN_HELPURL"] = "https://zh.wikipedia.org/wiki/子程序";
Blockly.Msg["PROCEDURES_DEFRETURN_RETURN"] = "返回";
Blockly.Msg["PROCEDURES_DEFRETURN_TOOLTIP"] = "创建一个有输出值的函数。";
Blockly.Msg["PROCEDURES_DEF_DUPLICATE_WARNING"] = "警告:此函数具有重复参数。";
Blockly.Msg["PROCEDURES_HIGHLIGHT_DEF"] = "突出显示函数定义";
Blockly.Msg["PROCEDURES_IFRETURN_HELPURL"] = "http://c2.com/cgi/wiki?GuardClause";
Blockly.Msg["PROCEDURES_IFRETURN_TOOLTIP"] = "如果值为真,则返回第二个值。";
Blockly.Msg["PROCEDURES_IFRETURN_WARNING"] = "警告:这个块只能在函数内部使用。";
Blockly.Msg["PROCEDURES_MUTATORARG_TITLE"] = "输入名称:";
Blockly.Msg["PROCEDURES_MUTATORARG_TOOLTIP"] = "添加函数输入。";
Blockly.Msg["PROCEDURES_MUTATORCONTAINER_TITLE"] = "输入";
Blockly.Msg["PROCEDURES_MUTATORCONTAINER_TOOLTIP"] = "添加、移除或重新排此函数的输入。";
Blockly.Msg["REDO"] = "重做";
Blockly.Msg["REMOVE_COMMENT"] = "删除注释";
Blockly.Msg["RENAME_VARIABLE"] = "重命名变量...";
Blockly.Msg["RENAME_VARIABLE_TITLE"] = "将所有“%1”变量重命名为:";
Blockly.Msg["TEXT_APPEND_HELPURL"] = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated
Blockly.Msg["TEXT_APPEND_TITLE"] = "向%1附加文本%2";
Blockly.Msg["TEXT_APPEND_TOOLTIP"] = "将一些文本追加到变量“%1”里。";
Blockly.Msg["TEXT_CHANGECASE_HELPURL"] = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated
Blockly.Msg["TEXT_CHANGECASE_OPERATOR_LOWERCASE"] = "转为小写";
Blockly.Msg["TEXT_CHANGECASE_OPERATOR_TITLECASE"] = "转为首字母大写";
Blockly.Msg["TEXT_CHANGECASE_OPERATOR_UPPERCASE"] = "转为大写";
Blockly.Msg["TEXT_CHANGECASE_TOOLTIP"] = "用不同的大小写模式复制并返回这段文字。";
Blockly.Msg["TEXT_CHARAT_FIRST"] = "寻找第一个字母";
Blockly.Msg["TEXT_CHARAT_FROM_END"] = "获取字符从倒数#";
Blockly.Msg["TEXT_CHARAT_FROM_START"] = "获取字符从#";
Blockly.Msg["TEXT_CHARAT_HELPURL"] = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated
Blockly.Msg["TEXT_CHARAT_LAST"] = "寻找最后一个字母";
Blockly.Msg["TEXT_CHARAT_RANDOM"] = "寻找随机的字母";
Blockly.Msg["TEXT_CHARAT_TAIL"] = "-";
Blockly.Msg["TEXT_CHARAT_TITLE"] = "在文本%1 里 %2";
Blockly.Msg["TEXT_CHARAT_TOOLTIP"] = "返回位于指定位置的字母。";
Blockly.Msg["TEXT_COUNT_HELPURL"] = "https://github.com/google/blockly/wiki/Text#counting-substrings";
Blockly.Msg["TEXT_COUNT_MESSAGE0"] = "计算%1在%2里出现的次数";
Blockly.Msg["TEXT_COUNT_TOOLTIP"] = "计算在一段文本中,某个部分文本重复出现了多少次。";
Blockly.Msg["TEXT_CREATE_JOIN_ITEM_TOOLTIP"] = "将一个项添加到文本中。";
Blockly.Msg["TEXT_CREATE_JOIN_TITLE_JOIN"] = "加入";
Blockly.Msg["TEXT_CREATE_JOIN_TOOLTIP"] = "添加、移除或重新排列各节来重新配置这个文本块。";
Blockly.Msg["TEXT_GET_SUBSTRING_END_FROM_END"] = "到最后一个字符#";
Blockly.Msg["TEXT_GET_SUBSTRING_END_FROM_START"] = "至字符#";
Blockly.Msg["TEXT_GET_SUBSTRING_END_LAST"] = "到最后一个字符";
Blockly.Msg["TEXT_GET_SUBSTRING_HELPURL"] = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated
Blockly.Msg["TEXT_GET_SUBSTRING_INPUT_IN_TEXT"] = "从文本";
Blockly.Msg["TEXT_GET_SUBSTRING_START_FIRST"] = "取得子串自第一个字符";
Blockly.Msg["TEXT_GET_SUBSTRING_START_FROM_END"] = "取得子串自倒数#";
Blockly.Msg["TEXT_GET_SUBSTRING_START_FROM_START"] = "取得子串自#";
Blockly.Msg["TEXT_GET_SUBSTRING_TAIL"] = "-";
Blockly.Msg["TEXT_GET_SUBSTRING_TOOLTIP"] = "返回文本中指定的一部分。";
Blockly.Msg["TEXT_INDEXOF_HELPURL"] = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated
Blockly.Msg["TEXT_INDEXOF_OPERATOR_FIRST"] = "寻找第一次出现的文本";
Blockly.Msg["TEXT_INDEXOF_OPERATOR_LAST"] = "寻找最后一次出现的文本";
Blockly.Msg["TEXT_INDEXOF_TITLE"] = "在文本 %1 里 %2 %3";
Blockly.Msg["TEXT_INDEXOF_TOOLTIP"] = "返回第一个文本段在第二个文本段中的第一/最后一个匹配项的起始位置。如果未找到,则返回%1。";
Blockly.Msg["TEXT_ISEMPTY_HELPURL"] = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated
Blockly.Msg["TEXT_ISEMPTY_TITLE"] = "%1是空的";
Blockly.Msg["TEXT_ISEMPTY_TOOLTIP"] = "如果给定的文本为空,则返回真。";
Blockly.Msg["TEXT_JOIN_HELPURL"] = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated
Blockly.Msg["TEXT_JOIN_TITLE_CREATEWITH"] = "建立文本从";
Blockly.Msg["TEXT_JOIN_TOOLTIP"] = "通过串起任意数量的项以建立一段文本。";
Blockly.Msg["TEXT_LENGTH_HELPURL"] = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated
Blockly.Msg["TEXT_LENGTH_TITLE"] = "%1的长度";
Blockly.Msg["TEXT_LENGTH_TOOLTIP"] = "返回给定文本的字母数(包括空格)。";
Blockly.Msg["TEXT_PRINT_HELPURL"] = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated
Blockly.Msg["TEXT_PRINT_TITLE"] = "输出%1";
Blockly.Msg["TEXT_PRINT_TOOLTIP"] = "输出指定的文字、数字或其他值。";
Blockly.Msg["TEXT_PROMPT_HELPURL"] = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated
Blockly.Msg["TEXT_PROMPT_TOOLTIP_NUMBER"] = "要求用户输入数字。";
Blockly.Msg["TEXT_PROMPT_TOOLTIP_TEXT"] = "要求用户输入一些文本。";
Blockly.Msg["TEXT_PROMPT_TYPE_NUMBER"] = "要求输入数字,并显示提示消息";
Blockly.Msg["TEXT_PROMPT_TYPE_TEXT"] = "要求输入文本,并显示提示消息";
Blockly.Msg["TEXT_REPLACE_HELPURL"] = "https://github.com/google/blockly/wiki/Text#replacing-substrings";
Blockly.Msg["TEXT_REPLACE_MESSAGE0"] = "在%3中将%1替换为%2";
Blockly.Msg["TEXT_REPLACE_TOOLTIP"] = "在一段文本中,将出现过的某部分文本都替换掉。";
Blockly.Msg["TEXT_REVERSE_HELPURL"] = "https://github.com/google/blockly/wiki/Text#reversing-text";
Blockly.Msg["TEXT_REVERSE_MESSAGE0"] = "翻转文本%1";
Blockly.Msg["TEXT_REVERSE_TOOLTIP"] = "将文本中各个字符的顺序倒转。";
Blockly.Msg["TEXT_TEXT_HELPURL"] = "https://zh.wikipedia.org/wiki/字符串";
Blockly.Msg["TEXT_TEXT_TOOLTIP"] = "一个字、词语或一行文本。";
Blockly.Msg["TEXT_TRIM_HELPURL"] = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated
Blockly.Msg["TEXT_TRIM_OPERATOR_BOTH"] = "消除其两侧的空白";
Blockly.Msg["TEXT_TRIM_OPERATOR_LEFT"] = "消除其左侧的空白";
Blockly.Msg["TEXT_TRIM_OPERATOR_RIGHT"] = "消除其右侧的空白";
Blockly.Msg["TEXT_TRIM_TOOLTIP"] = "从某一端或同时从两端删除多余的空白,并返回这段文字的一个副本。";
Blockly.Msg["TODAY"] = "今天";
Blockly.Msg["UNDO"] = "撤销";
Blockly.Msg["UNNAMED_KEY"] = "匿名";
Blockly.Msg["VARIABLES_DEFAULT_NAME"] = "项目";
Blockly.Msg["VARIABLES_GET_CREATE_SET"] = "创建“设定%1”";
Blockly.Msg["VARIABLES_GET_HELPURL"] = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated
Blockly.Msg["VARIABLES_GET_TOOLTIP"] = "返回此变量的值。";
Blockly.Msg["VARIABLES_SET"] = "赋值 %1 为 %2";
Blockly.Msg["VARIABLES_SET_CREATE_GET"] = "创建“获得%1”";
Blockly.Msg["VARIABLES_SET_HELPURL"] = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated
Blockly.Msg["VARIABLES_SET_TOOLTIP"] = "设置此变量,以使它和输入值相等。";
Blockly.Msg["VARIABLE_ALREADY_EXISTS"] = "名字叫“%1”的变量已经存在了。";
Blockly.Msg["VARIABLE_ALREADY_EXISTS_FOR_ANOTHER_TYPE"] = "名字叫“%1”的变量已经有了另一个类型“%2”。";
Blockly.Msg["WORKSPACE_ARIA_LABEL"] = "Blockly工作区";
Blockly.Msg["WORKSPACE_COMMENT_DEFAULT_TEXT"] = "说点什么...";
Blockly.Msg["CONTROLS_FOREACH_INPUT_DO"] = Blockly.Msg["CONTROLS_REPEAT_INPUT_DO"];
Blockly.Msg["CONTROLS_FOR_INPUT_DO"] = Blockly.Msg["CONTROLS_REPEAT_INPUT_DO"];
Blockly.Msg["CONTROLS_IF_ELSEIF_TITLE_ELSEIF"] = Blockly.Msg["CONTROLS_IF_MSG_ELSEIF"];
Blockly.Msg["CONTROLS_IF_ELSE_TITLE_ELSE"] = Blockly.Msg["CONTROLS_IF_MSG_ELSE"];
Blockly.Msg["CONTROLS_IF_IF_TITLE_IF"] = Blockly.Msg["CONTROLS_IF_MSG_IF"];
Blockly.Msg["CONTROLS_IF_MSG_THEN"] = Blockly.Msg["CONTROLS_REPEAT_INPUT_DO"];
Blockly.Msg["CONTROLS_WHILEUNTIL_INPUT_DO"] = Blockly.Msg["CONTROLS_REPEAT_INPUT_DO"];
Blockly.Msg["LISTS_CREATE_WITH_ITEM_TITLE"] = Blockly.Msg["VARIABLES_DEFAULT_NAME"];
Blockly.Msg["LISTS_GET_INDEX_HELPURL"] = Blockly.Msg["LISTS_INDEX_OF_HELPURL"];
Blockly.Msg["LISTS_GET_INDEX_INPUT_IN_LIST"] = Blockly.Msg["LISTS_INLIST"];
Blockly.Msg["LISTS_GET_SUBLIST_INPUT_IN_LIST"] = Blockly.Msg["LISTS_INLIST"];
Blockly.Msg["LISTS_INDEX_OF_INPUT_IN_LIST"] = Blockly.Msg["LISTS_INLIST"];
Blockly.Msg["LISTS_SET_INDEX_INPUT_IN_LIST"] = Blockly.Msg["LISTS_INLIST"];
Blockly.Msg["MATH_CHANGE_TITLE_ITEM"] = Blockly.Msg["VARIABLES_DEFAULT_NAME"];
Blockly.Msg["PROCEDURES_DEFRETURN_COMMENT"] = Blockly.Msg["PROCEDURES_DEFNORETURN_COMMENT"];
Blockly.Msg["PROCEDURES_DEFRETURN_DO"] = Blockly.Msg["PROCEDURES_DEFNORETURN_DO"];
Blockly.Msg["PROCEDURES_DEFRETURN_PROCEDURE"] = Blockly.Msg["PROCEDURES_DEFNORETURN_PROCEDURE"];
Blockly.Msg["PROCEDURES_DEFRETURN_TITLE"] = Blockly.Msg["PROCEDURES_DEFNORETURN_TITLE"];
Blockly.Msg["TEXT_APPEND_VARIABLE"] = Blockly.Msg["VARIABLES_DEFAULT_NAME"];
Blockly.Msg["TEXT_CREATE_JOIN_ITEM_TITLE_ITEM"] = Blockly.Msg["VARIABLES_DEFAULT_NAME"];
Blockly.Msg["MATH_HUE"] = "230";
Blockly.Msg["LOOPS_HUE"] = "120";
Blockly.Msg["LISTS_HUE"] = "260";
Blockly.Msg["LOGIC_HUE"] = "210";
Blockly.Msg["VARIABLES_HUE"] = "330";
Blockly.Msg["TEXTS_HUE"] = "160";
Blockly.Msg["PROCEDURES_HUE"] = "290";
Blockly.Msg["COLOUR_HUE"] = "20";
Blockly.Msg["VARIABLES_DYNAMIC_HUE"] = "310";

701
_server/css/editor.css Normal file
View File

@ -0,0 +1,701 @@
/** editor **/
:root {
--pixel: 416px;
}
html, body, div, img {
margin: 0;
padding: 0;
}
html, body {
width: 100%;
height: 100%;
overflow: hidden;
}
body {
font-family: Roboto, "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;;
}
/* ::-webkit-scrollbar {
width: 5px;
} */
.main {
max-width: 100%;
min-height: 500px;
margin: 0 auto;
}
.cp-app {
z-index: 250;
}
#colorPanel {
position: fixed;
width: max-content;
height: 205px;
z-index: 240;
padding: 4px 6px;
margin-top: 6px;
box-sizing: border-box;
}
#colorPicker {
margin: 2px 0;
border-radius: 3px;
width: 104px;
}
#left, #mid, #mid2, #right {
border-radius: 2px;
box-sizing: border-box;
}
#left {
position: absolute;
left: 5px;
top: 10px;
width: 435px;
height: 630px;
}
#mapEditArea {
position: absolute;
width: 100%;
height: 400px;
left: 0;
top: 0;
/* padding: 10px 5px; */
box-sizing: border-box;
}
#pout {
display: block;
width: 410px;
height: 380px;
box-sizing: border-box;
margin-left: 22px;
margin-top: 23px;
line-height: 20px;
font-size: 12.3px;
font-family: 'Lucida Console', Monaco, monospace;
white-space: pre;
border-radius: 2px;
overflow: auto;
}
#editTip {
position: absolute;
width: 100%;
left: 10px;
top: 430px;
}
#editBtns {
position: absolute;
width: 100%;
left: 10px;
top: 465px;
}
#newMaps {
position: absolute;
left: 10px;
top: 505px;
}
#newFloors {
position: absolute;
width: 100%;
left: 10px;
top: 530px;
}
#mapEditArea p {
margin: 10px;
display: block;
width: 70%;
line-height: 20px;
text-align: left;
font-size: 14px;
}
#editTip .btn {
float: right;
margin-right: 20px;
margin-top: 5px;
}
#mid {
position: absolute;
left: 448px;
top: 10px;
width: calc(24px + var(--pixel));
height: calc(422px + var(--pixel) / 2);
}
#mid2 {
position: absolute;
left: 448px;
top: calc(442px + var(--pixel) / 2);
width: calc(24px + var(--pixel));
bottom: 10px;
}
#mapEdit {
overflow: hidden;
}
.map {
position: absolute;
left: 20px;
top: 21px;
width: var(--pixel);
height: var(--pixel);
}
#lastUsedDiv {
height: auto;
bottom: 0;
margin-top: 20px;
overflow-x: hidden;
overflow-y: auto;
}
#mid .tools {
position: absolute;
width: calc(var(--pixel) + 9px);
height: calc(388px - var(--pixel) / 2);
left: 0;
bottom: 0;
padding: 10px 5px;
margin-left: 8px;;
box-sizing: border-box;
}
#tip {
float: right;
width: 48%;
height: 95%;
padding: 5px 10px 10px 10px;
margin-right: 0;
box-sizing: border-box;
border-radius: 2px;
font-size: 15px;
line-height: 18px;
}
#tip p {
margin-top: 10px;
margin-bottom: 10px;
}
.files {
width: 50%;
height: 120px;
/* padding: 10px; */
margin-top: 15px;
}
#bgSelect {
width: 50%;
height: 100px;
margin-top: 10px;
}
#bgSelect span {
/* display: block; */
font-size: 14px;
line-height: 30px;
}
#printOut {
margin-top: 10px;
height: 20px;
}
#right {
position: absolute;
left: calc(484px + var(--pixel));
top: 10px;
right: 0;
bottom: 0;
/* border: 1px solid rgb(238, 13, 13); */
}
#iconLib {
position: absolute;
right: 0;
bottom: 0;
left: 5px;
top: 5px;
overflow: auto;
}
#iconImages {
z-index: 0;
overflow: hidden;
}
#iconImages img {
position: absolute;
}
.gameCanvas {
position: absolute;
}
#dataSelection, .appendSelection {
position: absolute;
/* top:0;
left:320px; */
z-index: 75;
width: 26px;
height: 26px;
margin: 3px 0 0 3px;
padding: 0;
/* display: none; */
box-sizing: border-box;
}
#iconExpandBtn {
position: absolute;
left: 20px;
bottom: 30px;
font-size: 15px;
padding: 6px;
display: none;
}
.warnText {
font-weight: 700;
font-size: 14px;
line-height: 1.2em;
}
.successText {
line-height: 1.2em;
}
#mapColMark, #mapRowMark {
cursor: crosshair;
}
table.col {
position: relative;
text-align: center;
border-collapse: collapse;
}
#arrColMark td {
width: 16px;
}
#arrColMark {
top: 2px;
left: 36px;
width: 385px;
height: 16px;
font-size: 13px;
}
#mapColMark {
top: 2px;
left: 19px;
width: var(--pixel);
height: 16px;
font-size: 13px;
}
#mapColMark td {
width: 29px;
}
#mapColMark td:hover .colBlock {
position: absolute;
top: 19px;
height: var(--pixel);
width: 32px;
z-index: 100;
}
table.row {
position: relative;
text-align: right;
vertical-align: middle;
border-collapse: collapse;
}
#arrRowMark {
top: 5px;
left: 2px;
width: 16px;
height: 262px;
font-size: 12px;
}
#mapRowMark {
top: 1px;
left: 2px;
width: 16px;
height: var(--pixel);
font-size: 12px;
}
#mapRowMark td {
height: 29px;
}
#mapRowMark td:hover .rowBlock {
position: absolute;
left: 18px;
height: 32px;
width: var(--pixel);
z-index: 100;
}
#menuDiv * { margin: 0; padding: 0; }
#midMenu{
border-style: solid;
border-width: 1px;
cursor: default;
font: normal 13px Arial, sans-serif;
margin: 0;
outline: none;
padding: 4px 0;
position: absolute;
overflow-y: auto;
overflow-x: hidden;
max-height: 100%;
z-index: 101;
border-radius: 4px;
}
#midMenu .menuitem{
font: normal 13px Arial, sans-serif;
list-style: none;
margin: 0;
padding: 4px 7em 4px 28px;
white-space: nowrap;
/* padding-left: 12px; */
/* padding-right: 20px; */
}
#midMenu .menuitem:hover{
border-style: dotted;
border-width: 1px 0;
padding-bottom: 3px;
padding-top: 3px;
}
#midMenu .menuitem-content{
font: normal 13px Arial, sans-serif;
}
#searchBlock {
width: 100px;
border-radius: 10px;
outline: none;
padding-left: 20px;
height: 14px;
}
.searchLogo {
width: 15px;
height: 15px;
position: absolute;
left: 6px;
top: 6px;
background-image:url('data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGJhc2VQcm9maWxlPSJmdWxsIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWxuczpldj0iaHR0cDovL3d3dy53My5vcmcvMjAwMS94bWwtZXZlbnRzIj4KPGc%2BCgk8cG9seWdvbiBmaWxsPSIjNjY2IiBwb2ludHM9IjkuMjA3LDYuMTI2IDcuNzkzLDcuNTQxIDExLjc5MywxMS41NDEgMTMuMjA3LDEwLjEyNiIgLz4KCTxwYXRoIGZpbGw9IiM2NjYiIGQ9Ik01LjkxNywyYzEuNjA4LDAsMi45MTcsMS4zMDgsMi45MTcsMi45MTdTNy41MjUsNy44MzMsNS45MTcsNy44MzNTMyw2LjUyNSwzLDQuOTE3UzQuMzA4LDIsNS45MTcsMgoJCSBNNS45MTcsMEMzLjIwMSwwLDEsMi4yMDEsMSw0LjkxN3MyLjIwMSw0LjkxNyw0LjkxNyw0LjkxN3M0LjkxNy0yLjIwMSw0LjkxNy00LjkxN0MxMC44MzMsMi4yMDEsOC42MzIsMCw1LjkxNywwTDUuOTE3LDB6IiAvPgo8L2c%2BCjwvc3ZnPgo%3D');
}
#uieventDiv {
display: none;
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 2000
}
#uieventDialog {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -55%);
width: 560px;
}
#uieventHead {
margin: 10px 20px;
}
#uieventTitle {
font-weight: bold;
}
#uieventNo {
float: right;
}
#uieventYes {
display: none;
float: right;
margin-right: 15px;
}
#uieventBody {
width: 540px;
height: 540px;
position: relative;
margin-left: 10px;
margin-bottom: 5px;
overflow: hidden;
}
#uievent {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
}
#selectPoint {
display: none;
margin-left: 10px;
margin-bottom: 10px;
}
#selectPointFloor {
margin-right: 10px;
}
#selectPointButtons {
display: inline;
}
#selectPointBox {
position: absolute;
z-index: 75;
width: 26px;
height: 26px;
margin: 3px 0 0 3px;
padding: 0;
/* display: none; */
box-sizing: border-box;
}
/** editor_mode **/
.leftTab {
border-radius: 2px;
box-sizing: border-box;
overflow: auto;
position: absolute;
bottom: 0;
}
.leftTab > * {
margin: 2.5px 5px;
}
.leftTab > :first-child {
margin-top: 5px;
}
.leftTab > :last-child {
margin-bottom: 5px;
}
.leftTab {
left: 5px;
top: 10px;
width: 435px;
}
.leftTab .leftTabHeader {
position: fixed;
top: 15px;
left: 15px;
z-index: 20;
}
.leftTab .leftTabContent {
padding-top: 50px;
}
#appendPicSelection span {
position: absolute;
font-size: 11px;
}
#left6 {
left: 5px;
top: 5px;
z-index: 200;
position: fixed;
width: 100%;
height: 100%;
overflow: hidden;
}
#left6 #blocklyArea {
float: left;
width: 60%;
height: 95%;
}
#left6 #blocklyDiv {
position: relative;
}
#left6 .CodeMirror {
float: left;
height: 95%;
width: 35%;
}
#left6 #codeArea {
width: 99.5%;
height: 15.4em;
overflow: y; /* resize:none; */
}
#left7 {
/* height: 440px; width: 375px;float:left; */
left: 5px;
top: 5px;
z-index: 200;
position: fixed;
width: 100%;
height: 100%;
}
#left7 .CodeMirror {
/* border-top: 1px solid black;
border-bottom: 1px solid black; */
font-size: 14px;
height: 95%;
width: 95%;
}
.etable table, .etable table td {
cursor: auto;
}
/* copy from github-css https://github.com/sindresorhus/github-markdown-css */
.etable table {
border-spacing: 0;
border-collapse: collapse;
}
.etable table {
margin-top: 0;
margin-bottom: 16px;
}
.etable table {
display: block;
width: 100%;
overflow: auto;
word-break: break-all;
}
.etable table th {
font-weight: 600;
}
.etable table th,
.etable table td {
padding: 5px;
}
/* copy end --------------------------------------------- */
.etable tr {
width: 100%
}
.etable tr > :nth-child(1) {
width: 24%
}
.etable tr > :nth-child(2) {
width: 19%
}
.etable tr > :nth-child(3) {
width: 32%;
}
.etable tr > :nth-child(4) {
width: 25%;
padding: 0;
}
.etable table {
overflow: visible;
}
.etable tr:not(:first-child) > :nth-child(3) {
margin: 0;
padding: 0;
height: 100%;
position: relative;
}
.etable tr > :nth-child(4) {
text-align: center;
}
div.etableInputDiv {
position: absolute;
padding: 5px 0 0 5px;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
div.checkboxSet {
position: relative !important;
max-height: 250px;
overflow: auto;
}
.etableInputDiv > * {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
border: none;
background: transparent;
}
.etableInputDiv .checkbox {
width: 16px;
height: 16px;
position: absolute;
left: 50%;
top: 50%;
margin-left: -8px;
margin-top: -8px;
}
.etableInputDiv .checkboxSetMember {
width: 16px;
height: 16px;
display: inline-block;
}
.etableInputDiv textarea {
resize: none;
}
.etableInputDiv textarea:hover {
margin: -5px;
}

View File

@ -0,0 +1,587 @@
/** 配色文件:此文件包含了整个编辑器的全部配色 **/
/** ======== 编辑器主界面相关 ======== **/
/** 全局属性 **/
body {
background-color: #F5F5F5;
}
/** 可自行仿照添加更多的全局属性...... */
/** 颜色选择器 */
#colorPanel {
background-color: #F5F5F5;
}
/** 所有的阴影效果(颜色选择器、数据区、地图区、素材区等) */
#colorPanel, #left, #mid, #mid2, #right, .leftTab {
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12);
}
/** 地图编辑的输入框 */
#pout {
border: 1px solid #ddd;
}
/** 中间的消息提示框 */
#tip {
border: 1px solid #ccc;
}
/** 素材区背景 */
#iconLib, #mapEdit {
background-color: #F5F5F5;
}
/** 选中素材区时的方框 */
#dataSelection, .appendSelection, #selectPointBox {
background-color: rgba(255, 255, 255, 0.0);
border: 1px solid #000;
box-shadow: 0 0 0 2px #fff, 0 0 0 3px #000;
}
/** 错误消息(如保存失败) */
.warnText {
color: #D00;
}
/** 提示消息(如告知当前图块信息) */
.infoText {
color: #39F;
}
/** 成功消息(如保存成功) */
.successText {
color: #098;
}
/** 数据库的表格相关 */
table, td {
border: 1px solid #fff;
color: #fff;
}
.coltd, .rowtd {
border: 0.230vw solid #fff;
color: #fff;
}
/** 横向标尺背景色 */
table.col td, div.col .coltd {
background-color: #398;
}
/** 横向标尺选中时的背景色 */
#mapColMark td:hover .colBlock, #mapColMark .coltd:hover .colBlock {
background-color: rgba(85, 204, 187, 0.5);
}
/** 纵向标尺背景色 */
table.row td, div.row .rowtd .rowtext {
background-color: #379;
}
/** 纵向标尺选中时的背景色 */
#mapRowMark td:hover .rowBlock, #mapRowMark .rowtd:hover .rowBlock {
background-color: rgba(102, 170, 204, 0.5);
}
/** 右键菜单栏 */
#midMenu{
color: #000;
background-color: #fff;
border-color: #ccc #666 #666 #ccc;
}
#mid .tools {
border-top: 1px solid #ccc;
}
/** 右键菜单栏的当前选中项 */
#midMenu .menuitem:hover{
background-color: #cef;
border-color: #bde;
}
/** 禁用的输入方框如ID的背景色 */
textarea[disabled] {
color: #999999;
}
/** 搜索事件块的输入框 */
#searchBlock {
background-color: #eeeef4;
}
/** 打开浮层(变量搜索等)时页面背景 */
#uieventDiv {
background: rgba(128,128,128,0.6);
}
/** 浮层的对话框 */
#uieventDialog {
background: white;
}
/** 追加素材时的编号标记 */
#appendPicSelection span {
-webkit-text-stroke: 1px red;
text-shadow: black 1px 0, black 0 1px, black -1px 0, black 0 -1px;
}
.leftTab {
background-color: #F5F5F5;
}
/** 整个事件编辑器 */
#left6 {
background-color: rgb(245, 245, 245);
}
/** 事件编辑器右边的文本框 */
#left6 .CodeMirror {
border: 1px solid #eee;
}
/** 脚本编辑器 */
#left7 {
background-color: rgb(245, 245, 245);
}
#left7 .CodeMirror {
border: 1px solid #eee;
}
/** 数据区的表格 */
.etable table, .etable table td {
color: #000;
}
/** 数据区每行效果2n代表偶数行以此类推 */
.etable table tr {
background-color: #fff;
border-top: 1px solid #ccccd4;
}
.etable table tr:nth-child(2n) {
background-color: #fafafa;
}
/** 数据区表格每列效果 */
.etable table th, .etable table td {
border: 1px solid #ddd;
}
/** 鼠标悬停在数据区表格上的边框效果 */
.etable tr:not(:first-child) > :nth-child(3):hover {
border: 1px solid rgb(87, 198, 232);
box-shadow: 0px 0px 3px rgb(87, 198, 232);
}
.etable tr:not(:first-child) > :nth-child(2):hover,
.etable tr:not(:first-child) > :nth-child(1):hover {
border: 1px solid rgb(87, 232, 198);
box-shadow: 0px 0px 3px rgb(87, 232, 198);
}
/** 表格编辑的按钮颜色 */
.editorTableEditBtn {
background-color: #ddf8ff;
border-color: #bbc9cc;
color: #445560;
}
.editorTableFoldBtn {
background-color: #fff4bb;
border-color: #d4ccbb;
color: #605544;
}
/** 保存地图的按钮颜色 */
#saveFloor.highlight {
background-color: #ffd700;
border-color: #aa9944;
color: #430;
}
/** 解析按钮颜色 */
#blocklyParse.highlight {
background-color: #ffd700;
border-color: #aa9944;
color: #430;
}
/** 大地图按钮颜色 */
#bigmapBtn.highlight {
background-color: #ffd700;
border-color: #aa9944;
color: #430;
}
.popCheckboxItem {
color: black;
}
table.col td.highlight {
background-color: #77ddcc;
}
table.row td.highlight {
background-color: #88bbdd;
}
/** ======== blockly 相关 ======== */
/*魔改*/
.blocklyTreeLabel {
color: #0f0f0f !important;
}
.blocklyTreeLabel:hover {
/*background-color: #888 !important;*/
color: #0f0f0f !important;
}
.blocklyTreeSelected {
background-color: #5bf !important;
color: #fff !important;
}
.blocklyTreeRow {
color: #0f0f0f !important;
}
.blocklyTreeRow:hover {
background-color: #eee !important;
color: #0f0f0f !important;
}
/*魔改*/
/** 如果需要blockly深色模式请有选择性视情况取消注释下面几条具体功能自行研究 */
/*
.blocklyToolboxDiv {
background-color: #ddd !important;
color: black;
}
.blocklySvg {
background-color: #000;
}
.blocklyNonEditableText>rect, .blocklyEditableText>rect {
fill: #000;
fill-opacity: .4;
}
.blocklyNonEditableText>text, .blocklyEditableText>text {
fill: #fff;
}
input.blocklyHtmlInput {
color: white;
background-color: black;
}
*/
/** ======== Blockly中自动补全相关 ======== */
.awesomplete > ul {
background: #fff;
background: hsla(0,0%,100%,.9);
background: linear-gradient(to bottom right, white, hsla(0,0%,100%,.8));
border: 1px solid rgba(0,0,0,.3);
box-shadow: .05em .2em .6em rgba(0,0,0,.2);
}
.awesomplete > ul:before {
background: white;
}
.awesomplete > ul > li:hover {
background: #cef/*hsl(200, 40%, 80%)*/;
color: black;
}
.awesomplete > ul > li[aria-selected="true"] {
background: #39f/*hsl(205, 40%, 40%)*/;
color: white;
}
.awesomplete mark {
background: #cef;
}
.awesomplete li:hover mark {
background: #39f;
color: white;
}
.awesomplete li[aria-selected="true"] mark {
background: #06c;
color: inherit;
}
/** ======== 脚本编辑相关 ======== **/
/* 很多我也不知道是干嘛的,自行根据名字猜每一项作用吧 */
.CodeMirror {
color: black;
background: white;
}
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
background-color: white;
}
.CodeMirror-gutters {
border-right: 1px solid #ddd;
background-color: #f7f7f7;
}
.CodeMirror-linenumber {
color: #999;
}
.CodeMirror-guttermarker {
color: black;
}
.CodeMirror-guttermarker-subtle {
color: #999;
}
.CodeMirror-cursor {
border-left: 1px solid black;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver;
}
.cm-fat-cursor .CodeMirror-cursor {
background: #7e7;
}
.cm-fat-cursor-mark {
background-color: rgba(20, 255, 20, 0.5);
}
.cm-animate-fat-cursor {
background-color: #7e7;
}
.CodeMirror-ruler {
border-left: 1px solid #ccc;
}
/* DEFAULT THEME */
.cm-s-default .cm-header {
color: blue;
}
.cm-s-default .cm-quote {
color: #090;
}
.cm-negative {
color: #d44;
}
.cm-positive {
color: #292;
}
.cm-s-default .cm-keyword {
color: #819;
}
.cm-s-default .cm-atom {
color: #219;
}
.cm-s-default .cm-number {
color: #275;
}
.cm-s-default .cm-def {
color: #00f;
}
.cm-s-default .cm-variable-2 {
color: #05a;
}
.cm-s-default .cm-variable-3, .cm-s-default .cm-type {
color: #085;
}
.cm-s-default .cm-comment {
color: #960;
}
.cm-s-default .cm-string {
color: #a11;
}
.cm-s-default .cm-string-2 {
color: #f50;
}
.cm-s-default .cm-meta {
color: #555;
}
.cm-s-default .cm-qualifier {
color: #555;
}
.cm-s-default .cm-builtin {
color: #30a;
}
.cm-s-default .cm-bracket {
color: #997;
}
.cm-s-default .cm-tag {
color: #170;
}
.cm-s-default .cm-attribute {
color: #00c;
}
.cm-s-default .cm-hr {
color: #999;
}
.cm-s-default .cm-link {
color: #00c;
}
.cm-s-default .cm-error {
color: #f00;
}
.cm-invalidchar {
color: #f00;
}
/* Default styles for common addons */
div.CodeMirror span.CodeMirror-matchingbracket {
color: #0b0;
}
div.CodeMirror span.CodeMirror-nonmatchingbracket {
color: #a22;
}
.CodeMirror-matchingtag {
background: rgba(255, 150, 0, .3);
}
.CodeMirror-activeline-background {
background: #e8f2ff;
}
.CodeMirror-selected {
background: #d9d9d9;
}
.CodeMirror-focused .CodeMirror-selected {
background: #d7d4f0;
}
.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection {
background: #d7d4f0;
}
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection {
background: #d7d4f0;
}
.cm-searching {
background-color: #ffa;
background-color: rgba(255, 255, 0, .4);
}
/* 代码补全提示相关 */
.cm-matchhighlight {
background-color: #dedede
}
.CodeMirror-hints {
border: 1px solid silver;
background: white;
-webkit-box-shadow: 2px 3px 5px rgba(0, 0, 0, .2);
-moz-box-shadow: 2px 3px 5px rgba(0, 0, 0, .2);
box-shadow: 2px 3px 5px rgba(0, 0, 0, .2);
}
.CodeMirror-hint {
color: black;
}
li.CodeMirror-hint-active {
background: #08f;
color: white;
}
/* 代码语法检查相关相关 */
.CodeMirror-lint-tooltip {
background-color: #ffd;
border: 1px solid black;
color: black;
}
.CodeMirror-lint-mark-error {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==");
}
.CodeMirror-lint-mark-warning {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII=");
}
.CodeMirror-lint-marker-error, .CodeMirror-lint-message-error {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII=");
}
.CodeMirror-lint-marker-warning, .CodeMirror-lint-message-warning {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII=");
}
.CodeMirror-lint-marker-multiple {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAACVBMVEUAAAAAAAC/v7914kyHAAAAAXRSTlMAQObYZgAAACNJREFUeNo1ioEJAAAIwmz/H90iFFSGJgFMe3gaLZ0od+9/AQZ0ADosbYraAAAAAElFTkSuQmCC");
}
/* 代码补全的对话框(提供搜索功能)相关 */
.CodeMirror-dialog-top {
border-bottom: 1px solid #eee;
}
.CodeMirror-dialog-bottom {
border-top: 1px solid #eee;
}
/* 搜索项的背景色 */
.CodeMirror-focused .cm-matchhighlight {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAFklEQVQI12NgYGBgkKzc8x9CMDAwAAAmhwSbidEoSQAAAABJRU5ErkJggg==);
background-position: bottom;
background-repeat: repeat-x;
}
.cm-matchhighlight {background-color: lightgreen}
.CodeMirror-selection-highlight-scrollbar {background-color: yellowgreen}
.CodeMirror-search-hint {
color: #888;
}
/* 增强的代码补全系统相关 */
/* 变量类型 */
.CodeMirror-Tern-completion:before {
color: white;
}
.CodeMirror-Tern-completion-unknown:before {
content: "?";
background: #4bb;
}
.CodeMirror-Tern-completion-object:before {
content: "O";
background: #77c;
}
.CodeMirror-Tern-completion-fn:before {
content: "F";
background: #7c7;
}
.CodeMirror-Tern-completion-array:before {
content: "A";
background: #c66;
}
.CodeMirror-Tern-completion-number:before {
content: "1";
background: #999;
}
.CodeMirror-Tern-completion-string:before {
content: "S";
background: #999;
}
.CodeMirror-Tern-completion-bool:before {
content: "B";
background: #999;
}
.CodeMirror-Tern-completion-guess {
color: #999;
}
/* 额外提示框(如文档) */
.CodeMirror-Tern-tooltip {
border: 1px solid silver;
color: #444;
background-color: white;
-webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
-moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
box-shadow: 2px 3px 5px rgba(0,0,0,.2);
}
.CodeMirror-Tern-fname { color: black; }
.CodeMirror-Tern-farg { color: #70a; }
.CodeMirror-Tern-type { color: #07c; }
.CodeMirror-foldmarker {
color: blue;
text-shadow: #b9f 1px 1px 2px, #b9f -1px -1px 2px, #b9f 1px -1px 2px, #b9f -1px 1px 2px;
}

View File

@ -0,0 +1,756 @@
/** 配色文件:此文件包含了整个编辑器的全部配色 **/
/** ======== 编辑器主界面相关 ======== **/
/** 全局属性 **/
body {
background-color: #242424;
color: #bbb;
filter: brightness(0.825);
}
input {
background-color: #404048;
color: #c0c0c0;
}
button {
background-color: #404048;
border-color: #aaa;
color: #c0c0c0;
}
/** 可自行仿照添加更多的全局属性...... */
/** 颜色选择器 */
#colorPanel {
background-color: #333;
}
/** 所有的阴影效果(颜色选择器、数据区、地图区、素材区等) */
#colorPanel, #left, #mid, #mid2, #right, .leftTab {
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12);
}
/** 地图编辑的输入框 */
#pout {
border: 1px solid #ddd;
}
/** 中间的消息提示框 */
#tip {
border: 1px solid #ccc;
}
/** 素材区背景 */
#iconLib, #mapEdit {
background-color: #242424;
}
/** 选中素材区时的方框 */
#dataSelection, .appendSelection, #selectPointBox {
background-color: rgba(255, 255, 255, 0.0);
border: 1px solid #aaa;
box-shadow: 0 0 0 2px #ddd, 0 0 0 3px #aaa;
}
/** 错误消息(如保存失败) */
.warnText {
color: #e44;
}
/** 提示消息(如告知当前图块信息) */
.infoText {
color: #7bd;
}
/** 成功消息(如保存成功) */
.successText {
color: #8ca;
}
/** 数据库的表格相关 */
table, td {
border: 1px solid #777;
color: #777;
}
.coltd, .rowtd {
border: 0.230vw solid #777;
color: #777;
}
/** 横向标尺背景色 */
table.col td, div.col .coltd {
background-color: #287;
border-color: #ccc;
color: #ccc;
}
/** 横向标尺选中时的背景色 */
#mapColMark td:hover .colBlock, #mapColMark .coltd:hover .colBlock {
background-color: rgba(68, 187, 170, 0.33);
}
/** 纵向标尺背景色 */
table.row td, div.row .rowtd .rowtext {
background-color: #268;
border-color: #ccc;
color: #ccc;
}
/** 纵向标尺选中时的背景色 */
#mapRowMark td:hover .rowBlock, #mapRowMark .rowtd:hover .rowBlock {
background-color: rgba(85, 153, 187, 0.33);
}
/** 右键菜单栏 */
#midMenu{
color: #bbb;/*文字颜色*/
background-color: #33333c;
border-color: #888 #666 #666 #888;
}
#mid .tools {
border-top: 1px solid #555;
}
/** 右键菜单栏的当前选中项 */
#midMenu .menuitem:hover{
background-color: #247;
border-color: #469;
color: #fff;
}
/*===============================自己加的东西======================================*/
select {
background-color: #33333c;
}
option {
background-color: #33333c;
}
a {
color: #7bd;
}
textarea {
color: #bbb;
}
::-webkit-scrollbar-track
{
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
border-radius: 8px;
background-color: #242424;
}
::-webkit-scrollbar
{
width: 8px;
height: 10px;
background-color: #242424;
}
::-webkit-scrollbar-thumb
{
border-radius: 8px;
-webkit-box-shadow: inset 0 0 3px rgba(0,0,0,.3);
box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
background-color: #bbb;
}
/** 禁用的输入方框如ID的背景色 */
textarea[disabled] {
color: #888;
}
select {
color: #ccc;
background-color: #33333c;
}
option {
filter: brightness(0.8);
background-color: #292930;
color: #9a9a9a;
}
option:checked {
filter: brightness(0.8);
background-color: #555/*#358*/;
color: #ddd;
}
.gameCanvas, img {
filter: brightness(0.85);
}
/** 搜索事件块的输入框 */
#searchBlock {
background-color: #bbb;
color: #444;
}
/** 打开浮层(变量搜索等)时页面背景 */
#uieventDiv {
background: rgba(85,85,85,0.67);
}
/** 浮层的对话框 */
#uieventDialog {
background: #101010;
color: #ccc;
}
/** 追加素材时的编号标记 */
#appendPicSelection span {
-webkit-text-stroke: 1px gold;
text-shadow: black 1px 0, black 0 1px, black -1px 0, black 0 -1px;
}
.leftTab {
background-color: #242424;
}
/** 整个事件编辑器 */
#left6 {
background-color: rgb(36, 36, 36);
}
/** 事件编辑器右边的文本框 */
#left6 .CodeMirror {
/*border: 1px solid #eee;*/
border: 1px solid #666;
background-color: #242424;
/*color: #ccc;*/
}
/** 脚本编辑器 */
#left7 {
background-color: rgb(36, 36, 36);
}
#left7 .CodeMirror {
border: 1px solid #666;
}
/** 数据区的表格 */
.etable table, .etable table td {
color: #bbb;
}
/** 数据区每行效果2n代表偶数行以此类推 */
.etable table tr {
background-color: #3c3c3c;
border-top: 1px solid #ccccd4;
}
.etable table tr:nth-child(2n) {
background-color: #343434;
}
/** 数据区表格每列效果 */
.etable table th, .etable table td {
border: 1px solid #777;
}
/** 鼠标悬停在数据区表格上的边框效果 */
.etable tr:not(:first-child) > :nth-child(3):hover {
border: 1px solid #468;
box-shadow: 0px 0px 3px #468;
}
.etable tr:not(:first-child) > :nth-child(2):hover,
.etable tr:not(:first-child) > :nth-child(1):hover {
border: 1px solid #375;
box-shadow: 0px 0px 3px #375;
}
/** 表格编辑的按钮颜色 */
.editorTableEditBtn {
background-color: #389;
border-color: #bde;/*8cf和fd8*/
color: #cef;
}
.editorTableFoldBtn {
background-color: #a83;
border-color: #edb;
color: #fec;
filter: brightness(0.95);
}
/** 保存地图的按钮颜色 */
#saveFloor {
background-color: #234;/*33333c*/
border-color: #abc;
color: #cdf;
}
#saveFloor.highlight {
background-color: #871;
border-color: #eda;
color: #fff4d0;
}
/** 解析按钮颜色 */
#blocklyParse {
background-color: #404048;
color: #c0c0c0;
}
#blocklyParse.highlight {
background-color: #871;
border-color: #eda;
color: #fff4d0;
}
#bigmapBtn {
background-color: #234;/*33333c*/
border-color: #abc;
color: #cdf;
}
#bigmapBtn.highlight {
background-color: #871;
border-color: #eda;
color: #fff4d0;
}
.popCheckboxItem {
color: #bbbbbb;
}
table.col td.highlight {
background-color: #66ccbb;
}
table.row td.highlight {
background-color: #77aacc;
}
/** ======== blockly 相关 ======== */
/**
blockly图块的的黑暗程度用opacity表示0到1之间
0表示表示纯亮色1表示纯黑色
*/
/** 如果需要blockly深色模式请有选择性视情况取消注释下面几条具体功能自行研究 */
/*somethingSOMETHING*/
/*.blocklyTreeLabel {
color: #ccc;
}*/
.blocklyTreeLabel:hover {
/*background-color: #888 !important;*/
color: #fff !important;
}
.blocklyTreeSelected {
background-color: #358 !important;
color: #fff !important;
}
/*.blocklyTreeSelected .blocklyTreeLabel {
background-color: #358 !important;
background: #358 !important;
color: #fff !important;
}*/
.blocklyTreeRow {
/*background-color: #888 !important;*/
color: #ccc !important;
}
.blocklyTreeRow:hover {
background-color: #666 !important;
color: #fff !important;
}
/*
.blocklyFlyout {
background-color: rgba(0,0,0,1);
}
*/
.blocklyFlyoutBackground {
fill: #666;
fill-opacity: 0.67;
}
/*somethingSOMETHING*/
.blocklyToolboxDiv {
background-color: #2a2a2a !important;
border: 1px solid #666;
color: black;
}
.blocklySvg {
background-color: #242424;
}
.blocklyNonEditableText>rect, .blocklyEditableText>rect {
fill: #000;
fill-opacity: .3;
}
.blocklyNonEditableText>text, .blocklyEditableText>text {
fill: #fff;
}
input.blocklyHtmlInput {
color: white;
background-color: black;
}
.blocklyFieldRect:not(.blocklyColourFieldRect) {
fill: #242424 !important;
}
.blocklyEditableText > .blocklyText {
fill: #eee !important;
}
.blocklyHtmlInput {
background: rgba(36,36,36,0.6);
color: #eee;
}
.blocklyDropDownDiv {
background-color: #33333c;
border: 1px solid rgba(0,0,0,.3);
border-color: #666;
box-shadow: .05em .2em .6em rgba(0,0,0,.2);
}
.blocklyDropDownDiv .goog-menuitem-content {
color: #eee;
}
.blocklyDropDownDiv .goog-menuitem-highlight {
background: #247/*hsl(200, 40%, 80%)*/;
color: #eee;
}
.blocklyWidgetDiv .goog-option-selected .goog-menuitem-checkbox,
.blocklyWidgetDiv .goog-option-selected .goog-menuitem-icon,
.blocklyDropDownDiv .goog-option-selected .goog-menuitem-checkbox,
.blocklyDropDownDiv .goog-option-selected .goog-menuitem-icon {
background: url(../blockly/media/sprites_white.png) no-repeat -48px -16px;
}
/** ======== Blockly中自动补全相关 ======== */
.awesomplete > ul {
background: #33333c;
/*background: hsla(0,0%,100%,.9);
background: linear-gradient(to bottom right, white, hsla(0,0%,100%,.8));*/
border: 1px solid rgba(0,0,0,.3);
border-color: #666;
box-shadow: .05em .2em .6em rgba(0,0,0,.2);
}
.awesomplete > ul:before {
background: white;
}
.awesomplete > ul > li:hover {
background: #247/*hsl(200, 40%, 80%)*/;
color: #fff;
}
.awesomplete > ul > li[aria-selected="true"] {
background: hsl(205, 40%, 40%);
color: white;
}
.awesomplete mark {
background: /*hsl(65, 100%, 50%);*/#278;
color: #cef;
}
.awesomplete li:hover mark {
background: /*hsl(68, 100%, 41%)*/#1a9;
color: #fff;
}
.awesomplete li[aria-selected="true"] mark {
background: /*hsl(86, 100%, 21%)*/#468;
color: inherit;
}
/** ======== 脚本编辑相关 ======== **/
/* 很多我也不知道是干嘛的,自行根据名字猜每一项作用吧 */
.CodeMirror {
color: #ddd;/*杨子默:我也不知道他是干啥用的*/
background: #242424;
}
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
background-color: #242424;
}
.CodeMirror-gutters {
border-right: 1px solid #666;
background-color: #2a2a2a;
}
.CodeMirror-linenumber {
color: #999;
}
.CodeMirror-guttermarker {
color: black;
}
.CodeMirror-guttermarker-subtle {
color: #999;
}
.CodeMirror-cursor {
border-left: 1px solid #f8f8f0;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver;
}
.cm-fat-cursor .CodeMirror-cursor {
background: #7e7;
}
.cm-fat-cursor-mark {
background-color: rgba(20, 255, 20, 0.5);
}
.cm-animate-fat-cursor {
background-color: #7e7;
}
.CodeMirror-ruler {
border-left: 1px solid #ccc;
}
/* DEFAULT THEME */
.cm-s-default .cm-header {
color: #a8f;
}
.cm-s-default .cm-quote {
color: #695;
}
.cm-negative {
color: #f55;
}
.cm-positive {
color: #5f5;
}
.cm-s-default .cm-keyword {
color: #d7a;
}
.cm-s-default .cm-atom {
color: #80c0ff;
}
.cm-s-default .cm-number {
color: #a0e0c0;
}
.cm-s-default .cm-def {
color: #db7;
}
.cm-s-default .cm-variable-2 {
color: #8cd;
}
.cm-s-default .cm-variable-3, .cm-s-default .cm-type {
color: #8cd;
}
.cm-s-default .cm-comment {
color: #7a6;
}
.cm-s-default .cm-string {
color: #db7;
}
.cm-s-default .cm-string-2 {
color: #db7/*something?*/;
}
.cm-s-default .cm-meta {
color: #33333c;
}
.cm-s-default .cm-qualifier {
color: #33333c;
}
.cm-s-default .cm-builtin {
color: #66d9ef;
}
.cm-s-default .cm-bracket {
color: #f8f8f2;
}
.cm-s-default .cm-tag {
color: #f55;
}
.cm-s-default .cm-attribute {
color: #ab6;
}
.cm-s-default .cm-hr {
color: #999;
}
.cm-s-default .cm-link {
color: #a8f;
}
.cm-s-default .cm-error {
background: #f55;
color: #fff;
}
/*somethingsomething*/
.cm-s-default .cm-matchhighlight {
background: #57a;
color: #eef8ff;
}
/*somethingsomething*/
.cm-invalidchar {
color: #f55;
}
/* Default styles for common addons */
div.CodeMirror span.CodeMirror-matchingbracket {
color: #5f5;
}
div.CodeMirror span.CodeMirror-nonmatchingbracket {
color: #f55;
}
.CodeMirror-matchingtag {
background: rgba(255, 150, 0, .3);
}
.CodeMirror-activeline-background {
background: #247;
}
.CodeMirror-selected {
background: #358;
}
.CodeMirror-focused .CodeMirror-selected {
background: #358;
}
.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection {
background: #247;
}
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection {
background: #247;
}
.cm-searching {
background-color: #ffa;
background-color: rgba(255, 255, 0, .4);
}
/* 代码补全提示相关 */
.cm-matchhighlight {
background-color: #247;
}
.CodeMirror-hints {
border: 1px solid #888;
background: #33333c;
-webkit-box-shadow: 2px 3px 5px rgba(0, 0, 0, .2);
-moz-box-shadow: 2px 3px 5px rgba(0, 0, 0, .2);
box-shadow: 2px 3px 5px rgba(0, 0, 0, .2);
}
.CodeMirror-hint {
color: #ccc;
}
li.CodeMirror-hint-active {
background: #247;
color: #fff;
}
/* 代码语法检查相关相关 */
.CodeMirror-lint-tooltip {
background-color: #247;
border: 1px solid #135;
color: #fff;
}
.CodeMirror-lint-mark-error {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==");
}
.CodeMirror-lint-mark-warning {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII=");
}
.CodeMirror-lint-marker-error, .CodeMirror-lint-message-error {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII=");
}
.CodeMirror-lint-marker-warning, .CodeMirror-lint-message-warning {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII=");
}
.CodeMirror-lint-marker-multiple {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAACVBMVEUAAAAAAAC/v7914kyHAAAAAXRSTlMAQObYZgAAACNJREFUeNo1ioEJAAAIwmz/H90iFFSGJgFMe3gaLZ0od+9/AQZ0ADosbYraAAAAAElFTkSuQmCC");
}
/* 代码补全的对话框(提供搜索功能)相关 */
.CodeMirror-dialog-top {
border-bottom: 1px solid #eee;
}
.CodeMirror-dialog-bottom {
border-top: 1px solid #eee;
}
/* 搜索项的背景色 */
.CodeMirror-focused .cm-matchhighlight {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAFklEQVQI12NgYGBgkKzc8x9CMDAwAAAmhwSbidEoSQAAAABJRU5ErkJggg==);
background-position: bottom;
background-repeat: repeat-x;
}
.cm-matchhighlight {background-color: lightgreen}
.CodeMirror-selection-highlight-scrollbar {background-color: yellowgreen}
.CodeMirror-search-hint {
color: #888;
}
/* 增强的代码补全系统相关 */
/* 变量类型 */
.CodeMirror-Tern-completion:before {
color: white;
}
.CodeMirror-Tern-completion-unknown:before {
content: "?";
background: #4bb;
}
.CodeMirror-Tern-completion-object:before {
content: "O";
background: #77c;
}
.CodeMirror-Tern-completion-fn:before {
content: "F";
background: #7c7;
}
.CodeMirror-Tern-completion-array:before {
content: "A";
background: #c66;
}
.CodeMirror-Tern-completion-number:before {
content: "1";
background: #999;
}
.CodeMirror-Tern-completion-string:before {
content: "S";
background: #999;
}
.CodeMirror-Tern-completion-bool:before {
content: "B";
background: #999;
}
.CodeMirror-Tern-completion-guess {
color: #999;
}
/* 额外提示框(如文档) */
.CodeMirror-Tern-tooltip {
border: 1px solid #aaa;
color: #ccc;
background-color: #33333c;
-webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
-moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
box-shadow: 2px 3px 5px rgba(0,0,0,.2);
}
.CodeMirror-Tern-fname { color: #ddd; }
.CodeMirror-Tern-farg { color: #d7a; }
.CodeMirror-Tern-type { color: #db7; }
.CodeMirror-foldmarker {
color: #ddd;
text-shadow: #b9f 1px 1px 2px, #b9f -1px -1px 2px, #b9f 1px -1px 2px, #b9f -1px 1px 2px;
}

View File

@ -0,0 +1,712 @@
/** editor **/
:root {
--size: 13;
}
html{
font-size: 4vw;
}
input, textarea, select, button {
font-size: 1rem;
}
html, body, div, img {
margin: 0;
padding: 0;
}
body {
font-family: Roboto, "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;;
}
/* ::-webkit-scrollbar {
width: 5px;
} */
.main {
max-width: 100%;
min-height: 500px;
margin: 0 auto;
}
#left, #mid, #right {
/* border-radius: 2px;
box-sizing: border-box;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12); */
width: 100vw;
height: 100vw;
}
#left {
position: absolute;
}
#mapEditArea {
position: absolute;
width: 100%;
height: 70%;
left: 0;
top: 0;
/* padding: 10px 5px; */
box-sizing: border-box;
display: none;
}
#pout {
display: block;
width: 95vw;
height: 62vw;
box-sizing: border-box;
margin-left: 5vw;
margin-top: 23px;
line-height: 5vw;
font-size: 12px;
font-family: 'Lucida Console', Monaco, monospace;
white-space: pre;
border-radius: 2px;
overflow: auto;
}
#mapEditArea p {
margin: 10px;
display: block;
width: 70%;
line-height: 20px;
text-align: left;
font-size: 14px;
}
#editTip {
position: absolute;
width: 95vw;
left: 4vw;
top: 4vw;
}
#editTip .btn {
float: right;
margin-right: 20px;
margin-top: 5px;
}
#editBtns {
position: absolute;
width: 95vw;
left: 4vw;
top: 20vw;
}
#newMaps {
position: absolute;
left: 4vw;
top: 35vw;
}
#newFloors {
position: absolute;
width: 95vw;
left: 4vw;
top: 43vw;
}
#mid {
position: absolute;
}
#mid2 {
display: none;
}
#mapEdit {
overflow: hidden;
}
.map {
position: absolute;
left: 4vw;
top: 4vw;
width: 96vw;
height: 96vw;
}
.map canvas{
width: 96vw;
height: 96vw;
}
#mid .tools {
position: absolute;
width: 425px;
height: 180px;
left: 0;
bottom: 0;
padding: 10px 5px;
margin-left: 8px;;
box-sizing: border-box;
}
#tip {
float: right;
width: 45%;
/* height: 95%; */
min-height: 9rem;
padding: 5px 10px 10px 10px;
margin-right: 0;
box-sizing: border-box;
border-radius: 2px;
font-size: 1rem;
line-height: 1.2rem;
}
#tip p{
margin: 0.5rem
}
.files {
width: 50%;
height: 120px;
/* padding: 10px; */
margin-top: 15px;
}
#bgSelect {
width: 50%;
height: 100px;
margin-top: 10px;
}
#bgSelect span {
/* display: block; */
font-size: 14px;
line-height: 30px;
}
#printOut {
margin-top: 10px;
height: 20px;
}
#right {
position: absolute;
/* border: 1px solid rgb(238, 13, 13); */
}
#iconLib {
position: absolute;
width: 100vw;
height: 100vw;
top: 5px;
overflow: auto;
}
#iconImages {
z-index: 0;
overflow: hidden;
}
#iconImages img {
position: absolute;
}
.gameCanvas {
position: absolute;
}
#dataSelection, .appendSelection {
position: absolute;
/* top:0;
left:320px; */
z-index: 75;
width: 26px;
height: 26px;
margin: 3px 0 0 3px;
padding: 0;
/* display: none; */
box-sizing: border-box;
}
#iconExpandBtn {
position: absolute;
left: 20px;
bottom: 30px;
font-size: 15px;
padding: 6px;
display: none;
}
.warnText {
font-weight: 700;
font-size: 14px;
line-height: 1.2em;
}
.successText {
line-height: 1.2em;
}
td, .coltd, .rowtd {
cursor: crosshair;
}
table.col, div.col {
position: relative;
text-align: center;
border-collapse: collapse;
}
#arrColMark td {
width: 16px;
}
#arrColMark {
top: 2px;
left: 5vw;
width: 95vw;
height: 16px;
font-size: 13px;
display: none;
}
#mapColMark {
position: absolute;
top: 0;
left: 4vw;
width: 96vw;
height: 4vw;
font-size: 3vw;
}
#mapColMark .coltd,
#mapColMark .coltd .coltext {
position: absolute;
width: calc(93vw / var(--size));
height: 4vw;
line-height: 4vw;
padding: 0;
border-bottom-width: 0px;
border-top-width: 0px;
border-left-width: calc(1.5vw / var(--size));
border-right-width: calc(1.5vw / var(--size));
}
#mapColMark .coltd:hover .colBlock {
position: absolute;
top: 4vw;
left:0;
height: 96vw;
width: calc(96vw / var(--size));
z-index: 100;
}
table.row,div.row,
table.row,div.row .rowtext {
width:4vw;
position: relative;
text-align: right;
vertical-align: middle;
border-collapse: collapse;
}
#arrRowMark {
top: 5px;
left: 0;
width: 4vw;
height: 62vw;
font-size: 12px;
display: none;
}
#mapRowMark {
position: absolute;
top: 4vw;
left: 0;
width: 4vw;
height: 96vw;
font-size: 3vw;
}
#mapRowMark .rowtd{
position: absolute;
}
#mapRowMark .rowtd,
#mapRowMark .rowtd .rowtext{
height: calc(93vw / var(--size));
line-height: calc(93vw / var(--size));
padding: 0;
border-left-width: 0px;
border-right-width: 0px;
border-top-width: calc(1.5vw / var(--size));
border-bottom-width: calc(1.5vw / var(--size));
}
#mapRowMark .rowtd:hover .rowBlock {
position: absolute;
left: 4vw;
top: 0;
height: calc(96vw / var(--size));
width: 96vw;
z-index: 100;
}
#menuDiv * { margin: 0; padding: 0; }
#midMenu{
border-style: solid;
border-width: 1px;
cursor: default;
font: normal 2.5vw Arial, sans-serif;
margin: 0;
outline: none;
padding: 4px 0;
overflow-y: auto;
overflow-x: hidden;
max-height: 100%;
max-width: 40%;
z-index: 101;
border-radius: 4px;
}
#midMenu .menuitem{
font: normal 2.5vw Arial, sans-serif;
list-style: none;
margin: 0;
padding: 4px 7em 4px 4px;
white-space: nowrap;
/* padding-left: 12px; */
/* padding-right: 20px; */
}
#midMenu .menuitem:hover{
border-style: dotted;
border-width: 1px 0;
padding-bottom: 3px;
padding-top: 3px;
}
#midMenu .menuitem-content{
font: normal 2.5vw Arial, sans-serif;
}
#down{
position: absolute;
left:0;
top:100vw;
bottom: 0;
width: 100vw;
}
#colorPanel {
position: fixed;
width: max-content;
height: 205px;
z-index: 240;
padding: 4px 6px;
margin-top: 6px;
box-sizing: border-box;
}
#colorPicker {
margin: 2px 0;
border-radius: 3px;
width: 90px;
}
#uieventDiv {
display: none;
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 2000
}
#uieventDialog {
position: fixed;
top: 50%;
left: 0;
transform: translateY(-50%);
width: 100vw;
}
#uieventHead {
margin: 10px 20px;
}
#uieventTitle {
font-weight: bold;
}
#uieventNo {
float: right;
}
#uieventYes {
display: none;
float: right;
margin-right: 15px;
}
#uieventBody {
width: 100vw;
height: 100vw;
position: relative;
margin-left: 0;
margin-bottom: 5px;
overflow: hidden;
}
#uievent {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
}
#selectPoint {
display: none;
margin-left: 10px;
margin-bottom: 10px;
}
#selectPointFloor {
margin-right: 10px;
}
#selectPointButtons {
display: inline;
}
#selectPointBox {
position: absolute;
z-index: 75;
width: 26px;
height: 26px;
margin: 3px 0 0 3px;
padding: 0;
/* display: none; */
box-sizing: border-box;
}
/** editor_mode **/
.leftTab {
width: 100vw;
height: 100vw;
}
.leftTab {
overflow: auto;
position: absolute;
height: 100vw;
}
.leftTab > * {
margin: 2.5px 5px;
}
.leftTab > :first-child {
margin-top: 5px;
}
.leftTab > :last-child {
margin-bottom: 5px;
}
.leftTab {
left: 0;
top: 0;
width: 100vw;
}
.leftTab .leftTabHeader {
position: fixed;
top: 15px;
left: 15px;
}
.leftTab .leftTabContent {
padding-top: 50px;
}
#appendPicSelection span {
position: absolute;
font-size: 11px;
}
#left6 {
left: 0;
top: 0;
z-index: 200;
position: fixed;
width: 100%;
height: 100%;
overflow-x: hidden;
overflow-y: auto;
}
#left6 h3{
font-size: 6vw;
margin: 1.77vw 0;
}
#left6 #blocklyArea {
width: 100vw;
height: 100vw;
}
#left6 #blocklyDiv {
position: relative;
}
#left6 .CodeMirror {
height: 38vw;
width: 100%;
}
#left6 #codeArea {
width: 99.5%;
height: 15.4em;
overflow: y; /* resize:none; */
}
#left6 #blocklyDiv .blocklyToolboxDiv{
width:6vw;
}
#left6 #blocklyDiv .blocklyTreeLabel{
margin-left:-4vw;
}
#left7 {
/* height: 440px; width: 375px;float:left; */
left: 0;
top: 0;
z-index: 200;
position: fixed;
width: 100%;
height: 100%;
}
#left7 .CodeMirror {
font-size: 14px;
height: 95%;
width: 95%;
}
.etable table,
.etable table td {
cursor: auto;
}
/* copy from github-css https://github.com/sindresorhus/github-markdown-css */
.etable table {
border-spacing: 0;
border-collapse: collapse;
}
.etable table {
margin-top: 0;
margin-bottom: 16px;
}
.etable table {
display: block;
width: 100%;
overflow: auto;
word-break: break-all;
}
.etable table th {
font-weight: 600;
}
.etable table th,
.etable table td {
padding: 5px;
}
/* copy end --------------------------------------------- */
.etable tr {
width: 100%
}
.etable tr > :nth-child(1) {
width: 20%
}
.etable tr > :nth-child(2) {
width: 20%
}
.etable tr > :nth-child(3) {
width: 38%;
}
.etable tr > :nth-child(4) {
width: 22%;
text-align: center;
}
.etable table {
overflow: visible;
}
.etable tr:not(:first-child) > :nth-child(3) {
margin: 0;
padding: 0;
height: 100%;
position: relative;
}
div.etableInputDiv {
position: absolute;
padding: 5px 0 0 5px;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
div.checkboxSet {
position: relative !important;
max-height: 250px;
overflow: auto;
}
.etableInputDiv > * {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
border: none;
background: transparent;
}
.etableInputDiv .checkbox {
width: 16px;
height: 16px;
position: absolute;
left: 50%;
top: 50%;
margin-left: -8px;
margin-top: -8px;
}
.etableInputDiv .checkboxSetMember {
width: 16px;
height: 16px;
display: inline-block;
}
.etableInputDiv textarea {
resize: none;
}
.etableInputDiv textarea:hover {
margin: -5px;
}

1054
_server/editor.js Normal file

File diff suppressed because it is too large Load Diff

1213
_server/editor_blockly.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,705 @@
editor_blocklyconfig=(function(){
// start mark sfergsvae
(function(){
var getCategory = function(name,custom){
for(var node of document.getElementById('toolbox').children) {
if(node.getAttribute('name')==name) return node;
}
var node = document.createElement('category');
node.setAttribute('name',name);
if(custom)node.setAttribute('custom',custom);
document.getElementById('toolbox').appendChild(node);
return node;
}
var toolboxObj = {
'入口方块':[
'<label text="入口方块会根据当前类型在此数组中筛选,具体控制在editor_blockly.entranceCategoryCallback中"></label>',
MotaActionFunctions.actionParser.parse([
"欢迎使用事件编辑器",
"本事件触发一次后会消失",
{"type": "hide", "time": 500},
],'event'),
MotaActionFunctions.actionParser.parse({
"condition": "flag:__door__===2",
"currentFloor": true,
"priority": 0,
"delayExecute": false,
"multiExecute": false,
"data": [
{"type": "openDoor", "loc": [10,5]}
],
},'autoEvent'),
MotaActionBlocks['changeFloor_m'].xmlText(),
MotaActionFunctions.actionParser.parse([{
"id": "shop1",
"text": "\t[贪婪之神,moneyShop]勇敢的武士啊, 给我${20+2*flag:shop1}金币就可以:",
"textInList": "1F金币商店",
"choices": [
{"text": "生命+800", "need": "status:money>=20+2*flag:shop1", "action": [
{"type": "comment", "text": "新版商店中需要手动扣减金币和增加访问次数"},
{"type": "setValue", "name": "status:money", "operator": "-=", "value": "20+2*flag:shop1"},
{"type": "setValue", "name": "flag:shop1", "operator": "+=", "value": "1"},
{"type": "setValue", "name": "status:hp", "operator": "+=", "value": "800"}
]}
]
},{
"id": "itemShop",
"item": true,
"textInList": "道具商店",
"choices": [
{"id": "yellowKey", "number": 10, "money": 10}
]
},{
"id": "keyShop1",
"textInList": "回收钥匙商店",
"commonEvent": "回收钥匙商店",
"args": ""
}],'shop'),
MotaActionBlocks['common_m'].xmlText(),
MotaActionBlocks['beforeBattle_m'].xmlText(),
MotaActionBlocks['afterBattle_m'].xmlText(),
MotaActionBlocks['afterGetItem_m'].xmlText(),
MotaActionBlocks['afterOpenDoor_m'].xmlText(),
MotaActionBlocks['firstArrive_m'].xmlText(),
MotaActionBlocks['eachArrive_m'].xmlText(),
MotaActionBlocks['level_m'].xmlText(),
MotaActionFunctions.actionParser.parse([
['MTx', '']
], 'floorPartition'),
MotaActionBlocks['commonEvent_m'].xmlText(),
MotaActionBlocks['item_m'].xmlText(),
MotaActionFunctions.actionParser.parse([
{"title":"简单", "name": "Easy", "hard": 1, "action": [
{"type": "comment", "text": "在这里写该难度需执行的事件"}
]}
], 'levelChoose'),
MotaActionFunctions.actionParser.parse({
"type": 0, "value": {"atk": 10}, "percentage": {"speed": 10},
}, 'equip'),
MotaActionFunctions.actionParser.parse([{
"name": "bg.jpg", "x": 0, "y": 0, "canvas": "bg"
}], 'floorImage'),
MotaActionFunctions.actionParser.parse({
"time": 160, "openSound": "door.mp3", "closeSound": "door.mp3", "keys": {"yellowKey": 1, "orangeKey": 1}
}, 'doorInfo'),
MotaActionBlocks['faceIds_m'].xmlText(),
MotaActionBlocks['mainStyle_m'].xmlText(),
MotaActionFunctions.actionParser.parse({
"背景音乐": "bgm.mp3", "确定": "confirm.mp3", "攻击": "attack.mp3", "背景图": "bg.jpg", "领域": "zone", "文件名": "file.jpg"
}, 'nameMap'),
MotaActionFunctions.actionParser.parse([
{"name": "hero.png", "width": 32, "height": 32, "prefix": "hero_"},
], 'splitImages'),
],
'显示文字':[
MotaActionBlocks['text_0_s'].xmlText(),
MotaActionBlocks['text_1_s'].xmlText(),
MotaActionFunctions.actionParser.parseList("\t[小妖精,fairy]\f[fairy.png,0,0]欢迎使用事件编辑器(双击方块可直接预览)"),
MotaActionBlocks['moveTextBox_s'].xmlText(),
MotaActionBlocks['clearTextBox_s'].xmlText(),
MotaActionBlocks['comment_s'].xmlText(),
MotaActionBlocks['autoText_s'].xmlText(),
MotaActionBlocks['scrollText_s'].xmlText(),
MotaActionBlocks['setText_s'].xmlText(),
MotaActionBlocks['tip_s'].xmlText(),
MotaActionBlocks['confirm_s'].xmlText(),
MotaActionBlocks['choices_s'].xmlText([
'选择剑或者盾','流浪者','man',0,'',MotaActionBlocks['choicesContext'].xmlText([
'剑','','',null,'','',MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [3,3]}]),
])
]),
MotaActionBlocks['win_s'].xmlText(),
MotaActionBlocks['lose_s'].xmlText(),
MotaActionBlocks['restart_s'].xmlText(),
],
'数据相关':[
MotaActionBlocks['setValue_s'].xmlText([
MotaActionBlocks['idIdList_e'].xmlText(['status','生命']), '=', '', false
]),
MotaActionBlocks['setEnemy_s'].xmlText(),
MotaActionBlocks['setEnemyOnPoint_s'].xmlText(),
MotaActionBlocks['resetEnemyOnPoint_s'].xmlText(),
MotaActionBlocks['moveEnemyOnPoint_s'].xmlText(),
MotaActionBlocks['moveEnemyOnPoint_1_s'].xmlText(),
MotaActionBlocks['setEquip_s'].xmlText(),
MotaActionBlocks['setFloor_s'].xmlText(),
MotaActionBlocks['setGlobalAttribute_s'].xmlText(),
MotaActionBlocks['setGlobalValue_s'].xmlText(),
MotaActionBlocks['setGlobalFlag_s'].xmlText(),
MotaActionBlocks['setNameMap_s'].xmlText(),
MotaActionBlocks['input_s'].xmlText(),
MotaActionBlocks['input2_s'].xmlText(),
MotaActionBlocks['update_s'].xmlText(),
MotaActionBlocks['moveAction_s'].xmlText(),
MotaActionBlocks['changeFloor_s'].xmlText(),
MotaActionBlocks['changePos_s'].xmlText(),
MotaActionBlocks['battle_s'].xmlText(),
MotaActionBlocks['useItem_s'].xmlText(),
MotaActionBlocks['loadEquip_s'].xmlText(),
MotaActionBlocks['unloadEquip_s'].xmlText(),
MotaActionBlocks['openShop_s'].xmlText(),
MotaActionBlocks['disableShop_s'].xmlText(),
MotaActionBlocks['setHeroIcon_s'].xmlText(),
MotaActionBlocks['follow_s'].xmlText(),
MotaActionBlocks['unfollow_s'].xmlText(),
],
'地图处理':[
MotaActionBlocks['battle_1_s'].xmlText(),
MotaActionBlocks['openDoor_s'].xmlText(),
MotaActionBlocks['closeDoor_s'].xmlText(),
MotaActionBlocks['show_s'].xmlText(),
MotaActionBlocks['hide_s'].xmlText(),
MotaActionBlocks['setBlock_s'].xmlText(),
MotaActionBlocks['setBlockOpacity_s'].xmlText(),
MotaActionBlocks['setBlockFilter_s'].xmlText(),
MotaActionBlocks['turnBlock_s'].xmlText(),
MotaActionBlocks['moveHero_s'].xmlText(),
MotaActionBlocks['move_s'].xmlText(),
MotaActionBlocks['jumpHero_s'].xmlText(),
MotaActionBlocks['jumpHero_1_s'].xmlText(),
MotaActionBlocks['jump_s'].xmlText(),
MotaActionBlocks['jump_1_s'].xmlText(),
MotaActionBlocks['showBgFgMap_s'].xmlText(),
MotaActionBlocks['hideBgFgMap_s'].xmlText(),
MotaActionBlocks['setBgFgBlock_s'].xmlText(),
MotaActionBlocks['showFloorImg_s'].xmlText(),
MotaActionBlocks['hideFloorImg_s'].xmlText(),
],
'事件控制':[
MotaActionBlocks['if_1_s'].xmlText(),
MotaActionBlocks['if_s'].xmlText(),
MotaActionFunctions.actionParser.parseList({"type": "switch", "condition": "判别值", "caseList": [
{"action": [{"type": "comment", "text": "当判别值是值的场合执行此事件"}]},
{"case": "default", "action": [{"type": "comment", "text": "当没有符合的值的场合执行default事件"}]},
]}),
MotaActionFunctions.actionParser.parseList({"type": "for", "name": "temp:A", "from": "0", "to": "12", "step": "1", "data": []}),
MotaActionFunctions.actionParser.parseList({"type": "forEach", "name": "temp:A", "list": ["status:atk","status:def"], "data": []}),
MotaActionBlocks['while_s'].xmlText(),
MotaActionBlocks['dowhile_s'].xmlText(),
MotaActionBlocks['break_s'].xmlText(),
MotaActionBlocks['continue_s'].xmlText(),
MotaActionBlocks['exit_s'].xmlText(),
MotaActionBlocks['trigger_s'].xmlText(),
MotaActionBlocks['insert_1_s'].xmlText(),
MotaActionBlocks['insert_2_s'].xmlText(),
],
'特效表现':[
MotaActionBlocks['sleep_s'].xmlText(),
MotaActionFunctions.actionParser.parseList({"type": "wait", "timeout": 0, "data": [
{"case": "keyboard", "keycode": "13,32", "action": [{"type": "comment", "text": "当按下回车(keycode=13)或空格(keycode=32)时执行此事件\n超时剩余时间会写入flag:timeout"}]},
{"case": "mouse", "px": [0,32], "py": [0,32], "action": [{"type": "comment", "text": "当点击地图左上角时执行此事件\n超时剩余时间会写入flag:timeout"}]},
{"case": "condition", "condition": "flag:type==0\n&&flag:keycode==13", "action": [{"type": "comment", "text": "当满足自定义条件时会执行此事件\n超时剩余时间会写入flag:timeout"}]},
{"case": "timeout", "action": [{"type": "comment", "text": "当超时未操作时执行此事件"}]},
]}),
MotaActionBlocks['waitAsync_s'].xmlText(),
MotaActionBlocks['stopAsync_s'].xmlText(),
MotaActionBlocks['vibrate_s'].xmlText(),
MotaActionBlocks['animate_s'].xmlText(),
MotaActionBlocks['animate_1_s'].xmlText(),
MotaActionBlocks['stopAnimate_s'].xmlText(),
MotaActionBlocks['setViewport_s'].xmlText(),
MotaActionBlocks['setViewport_1_s'].xmlText(),
MotaActionBlocks['lockViewport_s'].xmlText(),
MotaActionBlocks['showStatusBar_s'].xmlText(),
MotaActionBlocks['hideStatusBar_s'].xmlText(),
MotaActionBlocks['setHeroOpacity_s'].xmlText(),
MotaActionBlocks['setCurtain_0_s'].xmlText(),
MotaActionBlocks['setCurtain_1_s'].xmlText(),
MotaActionBlocks['screenFlash_s'].xmlText(),
MotaActionBlocks['setWeather_s'].xmlText(),
MotaActionBlocks['callBook_s'].xmlText(),
MotaActionBlocks['callSave_s'].xmlText(),
MotaActionBlocks['autoSave_s'].xmlText(),
MotaActionBlocks['forbidSave_s'].xmlText(),
MotaActionBlocks['callLoad_s'].xmlText(),
],
'音像处理':[
MotaActionBlocks['showImage_s'].xmlText(),
MotaActionBlocks['showImage_1_s'].xmlText(),
MotaActionBlocks['hideImage_s'].xmlText(),
MotaActionBlocks['showTextImage_s'].xmlText(),
MotaActionBlocks['moveImage_s'].xmlText(),
MotaActionBlocks['rotateImage_s'].xmlText(),
MotaActionBlocks['scaleImage_s'].xmlText(),
MotaActionBlocks['showGif_s'].xmlText(),
MotaActionBlocks['playBgm_s'].xmlText(),
MotaActionBlocks['pauseBgm_s'].xmlText(),
MotaActionBlocks['resumeBgm_s'].xmlText(),
MotaActionBlocks['loadBgm_s'].xmlText(),
MotaActionBlocks['freeBgm_s'].xmlText(),
MotaActionBlocks['playSound_s'].xmlText(),
MotaActionBlocks['playSound_1_s'].xmlText(),
MotaActionBlocks['stopSound_s'].xmlText(),
MotaActionBlocks['setVolume_s'].xmlText(),
MotaActionBlocks['setBgmSpeed_s'].xmlText(),
],
'UI绘制':[
MotaActionBlocks['previewUI_s'].xmlText(),
MotaActionBlocks['clearMap_s'].xmlText(),
MotaActionBlocks['setAttribute_s'].xmlText(),
MotaActionBlocks['setFilter_s'].xmlText(),
MotaActionBlocks['fillText_s'].xmlText(),
MotaActionBlocks['fillBoldText_s'].xmlText(),
MotaActionBlocks['drawTextContent_s'].xmlText(),
MotaActionBlocks['fillRect_s'].xmlText(),
MotaActionBlocks['strokeRect_s'].xmlText(),
MotaActionBlocks['drawLine_s'].xmlText(),
MotaActionBlocks['drawArrow_s'].xmlText(),
MotaActionBlocks['fillPolygon_s'].xmlText(),
MotaActionBlocks['strokePolygon_s'].xmlText(),
MotaActionBlocks['fillEllipse_s'].xmlText(),
MotaActionBlocks['strokeEllipse_s'].xmlText(),
MotaActionBlocks['fillArc_s'].xmlText(),
MotaActionBlocks['strokeArc_s'].xmlText(),
MotaActionBlocks['drawImage_s'].xmlText(),
MotaActionBlocks['drawImage_1_s'].xmlText(),
MotaActionBlocks['drawIcon_s'].xmlText(),
MotaActionBlocks['drawBackground_s'].xmlText(),
MotaActionBlocks['drawSelector_s'].xmlText(),
MotaActionBlocks['drawSelector_1_s'].xmlText(),
],
'原生脚本':[
MotaActionBlocks['function_s'].xmlText(),
MotaActionBlocks['unknown_s'].xmlText(),
],
'值块':[
MotaActionBlocks['setValue_s'].xmlText([
MotaActionBlocks['idIdList_e'].xmlText(['status','生命']), '=', '', false
]),
MotaActionBlocks['expression_arithmetic_0'].xmlText(),
MotaActionBlocks['idFlag_e'].xmlText(),
MotaActionBlocks['idTemp_e'].xmlText(),
MotaActionBlocks['negate_e'].xmlText(),
MotaActionBlocks['unaryOperation_e'].xmlText(),
MotaActionBlocks['bool_e'].xmlText(),
MotaActionBlocks['idString_e'].xmlText(),
MotaActionBlocks['idIdList_e'].xmlText(),
MotaActionBlocks['idFixedList_e'].xmlText(),
MotaActionBlocks['enemyattr_e'].xmlText(),
MotaActionBlocks['blockId_e'].xmlText(),
MotaActionBlocks['blockNumber_e'].xmlText(),
MotaActionBlocks['blockCls_e'].xmlText(),
MotaActionBlocks['hasEquip_e'].xmlText(),
MotaActionBlocks['equip_e'].xmlText(),
MotaActionBlocks['nextXY_e'].xmlText(),
MotaActionBlocks['isReplaying_e'].xmlText(),
MotaActionBlocks['hasVisitedFloor_e'].xmlText(),
MotaActionBlocks['isShopVisited_e'].xmlText(),
MotaActionBlocks['canBattle_e'].xmlText(),
MotaActionBlocks['damage_e'].xmlText(),
MotaActionBlocks['damage_1_e'].xmlText(),
MotaActionBlocks['rand_e'].xmlText(),
MotaActionBlocks['evalString_e'].xmlText(),
],
'常见事件模板':[
'<label text="检测音乐如果没有开启则系统提示开启"></label>',
MotaActionFunctions.actionParser.parseList({"type": "if", "condition": "!core.musicStatus.bgmStatus",
"true": [
"\t[系统提示]你当前音乐处于关闭状态,本塔开音乐游戏效果更佳"
],
"false": []
}),
'<label text="仿新新魔塔一次性商人"></label>',
MotaActionFunctions.actionParser.parse([
{
"type": "if",
"condition": "switch:A",
"true": [
"\t[行商,trader]\b[this]这是购买我的道具后我给玩家的提示。",
{
"type": "comment",
"text": "下一条指令可视情况使用或不使用"
},
{
"type": "hide",
"remove": true,
"time": 250
}
],
"false": [
{
"type": "confirm",
"text": "我有3把黄钥匙\n你出50金币就卖给你。",
"yes": [
{
"type": "if",
"condition": "status:money>=50",
"true": [
{
"type": "setValue",
"name": "status:money",
"operator": "-=",
"value": "50"
},
{
"type": "setValue",
"name": "item:yellowKey",
"operator": "+=",
"value": "3"
},
{
"type": "playSound",
"name": "确定",
"stop": true
},
{
"type": "setValue",
"name": "switch:A",
"value": "true"
}
],
"false": [
{
"type": "playSound",
"name": "操作失败"
},
"\t[行商,trader]\b[this]你的金币不足!"
]
}
],
"no": []
}
]
}
], 'event'),
'<label text="全地图选中一个点"></label>',
MotaActionFunctions.actionParser.parse([
{
"type": "comment",
"text": "全地图选中一个点,需要用鼠标或触屏操作"
},
{
"type": "setValue",
"name": "temp:X",
"value": "status:x"
},
{
"type": "setValue",
"name": "temp:Y",
"value": "status:y"
},
{
"type": "tip",
"text": "再次点击闪烁位置确认"
},
{
"type": "while",
"condition": "true",
"data": [
{
"type": "drawSelector",
"image": "winskin.png",
"code": 1,
"x": "32*temp:X",
"y": "32*temp:Y",
"width": 32,
"height": 32
},
{
"type": "wait"
},
{
"type": "if",
"condition": "(flag:type === 1)",
"true": [
{
"type": "if",
"condition": "((temp:X===flag:x)&&(temp:Y===flag:y))",
"true": [
{
"type": "break",
"n": 1
}
]
},
{
"type": "setValue",
"name": "temp:X",
"value": "flag:x"
},
{
"type": "setValue",
"name": "temp:Y",
"value": "flag:y"
}
]
}
]
},
{
"type": "drawSelector",
"code": 1
},
{
"type": "comment",
"text": "流程进行到这里可以对[X,Y]点进行处理,比如"
},
{
"type": "closeDoor",
"id": "yellowDoor",
"loc": [
"temp:X",
"temp:Y"
]
}
],'event'),
'<label text="多阶段Boss战斗"></label>',
MotaActionFunctions.actionParser.parse([
{
"type": "comment",
"text": "多阶段boss请直接作为战后事件使用"
},
{
"type": "setValue",
"name": "switch:A",
"operator": "+=",
"value": "1"
},
{
"type": "switch",
"condition": "switch:A",
"caseList": [
{
"case": "1",
"action": [
{
"type": "setBlock",
"number": "redSlime"
},
"\t[2阶段boss,redSlime]\b[this]你以为你已经打败我了吗?没听说过史莱姆有九条命吗?"
]
},
{
"case": "2",
"action": [
{
"type": "setBlock",
"number": "blackSlime"
},
"\t[3阶段boss,blackSlime]\b[this]不能消灭我的,只会让我更强大!"
]
},
{
"case": "3",
"action": [
{
"type": "setBlock",
"number": "slimelord"
},
"\t[4阶段boss,slimelord]\b[this]我还能打!"
]
},
{
"case": "4",
"action": [
"\t[4阶段boss,slimelord]我一定会回来的!"
]
}
]
}
],'afterBattle'),
],
'最近使用事件':[
'<label text="此处只是占位符,实际定义在editor_blockly.searchBlockCategoryCallback中"></label>',
]
}
var toolboxgap = '<sep gap="5"></sep>'
//xml_text = MotaActionFunctions.actionParser.parse(obj,type||'event')
//MotaActionBlocks['idString_e'].xmlText()
for (var name in toolboxObj){
var custom = null;
if(name=='最近使用事件')custom='searchBlockCategory';
if(name=='入口方块')custom='entranceCategory';
getCategory(name,custom).innerHTML = toolboxObj[name].join(toolboxgap);
}
var blocklyArea = document.getElementById('blocklyArea');
var blocklyDiv = document.getElementById('blocklyDiv');
var workspace = Blockly.inject(blocklyDiv,{
media: '_server/blockly/media/',
toolbox: document.getElementById('toolbox'),
zoom:{
controls: true,
wheel: false,//滚轮改为上下(shift:左右)翻滚
startScale: 1.0,
maxScale: 3,
minScale: 0.3,
scaleSpeed: 1.08
},
trashcan: false,
});
editor_blockly.isCommonEntry = function () {
var commonEntries = ['beforeBattle', 'afterBattle', 'afterOpenDoor', 'firstArrive', 'eachArrive', 'commonEvent', 'item'];
return commonEntries.indexOf(editor_blockly.entryType) >= 0;
}
editor_blockly.entranceCategoryCallback = function(workspace) {
var list=toolboxObj['入口方块']
var xmlList = [];
var eventType = (editor_blockly.isCommonEntry() ? 'common' : editor_blockly.entryType)+'_m';
for(var ii=0,blockText;blockText=list[ii];ii++){
if(new RegExp('<block type="'+eventType+'">').exec(blockText)){
var block = Blockly.Xml.textToDom('<xml>'+blockText+'</xml>').firstChild;
block.setAttribute("gap", 5);
xmlList.push(block);
}
}
return xmlList;
}
workspace.registerToolboxCategoryCallback(
'entranceCategory', editor_blockly.entranceCategoryCallback);
editor_blockly.searchBlockCategoryCallback = function(workspace) {
var xmlList = [];
var labels = editor_blockly.searchBlock();
for (var i = 0; i < labels.length; i++) {
var blockText = '<xml>' +
MotaActionBlocks[labels[i]].xmlText() +
'</xml>';
var block = Blockly.Xml.textToDom(blockText).firstChild;
block.setAttribute("gap", 5);
xmlList.push(block);
}
return xmlList;
};
workspace.registerToolboxCategoryCallback(
'searchBlockCategory', editor_blockly.searchBlockCategoryCallback);
var onresize = function(e) {
blocklyDiv.style.width = blocklyArea.offsetWidth + 'px';
blocklyDiv.style.height = blocklyArea.offsetHeight + 'px';
Blockly.svgResize(workspace);
};
if(typeof editor !== "undefined" && !editor.isMobile)window.addEventListener('resize', onresize, false);
onresize();
//Blockly.svgResize(workspace);
//Blockly.bindEventWithChecks_(workspace.svgGroup_,"wheel",workspace,function(e){});
document.getElementById('blocklyDiv').onmousewheel = function(e){
//console.log(e);
e.preventDefault();
var hvScroll = e.shiftKey?'hScroll':'vScroll';
var mousewheelOffsetValue=20/380*workspace.scrollbar[hvScroll].handleLength_*3;
workspace.scrollbar[hvScroll].handlePosition_+=( ((e.deltaY||0)+(e.detail||0)) >0?mousewheelOffsetValue:-mousewheelOffsetValue);
workspace.scrollbar[hvScroll].onScroll_();
// workspace.setScale(workspace.scale);
}
var doubleClickCheck=[[0,'abc']];
function omitedcheckUpdateFunction(event) {
if(event.type==='create'){
editor_blockly.addIntoLastUsedType(event.blockId);
}
if(event.type==='ui' && event.element == 'click'){
var newClick = [new Date().getTime(),event.blockId];
var lastClick = doubleClickCheck.shift();
doubleClickCheck.push(newClick);
if(newClick[0]-lastClick[0]<500){
if(newClick[1]===lastClick[1]){
editor_blockly.doubleClickBlock(newClick[1]);
}
}
}
// Only handle these events
if (["create", "move", "change", "delete"].indexOf(event.type) < 0) return;
if(editor_blockly.workspace.topBlocks_.length>=2){
editor_blockly.setValue('入口方块只能有一个');
return;
}
var eventType = editor_blockly.entryType;
if(editor_blockly.workspace.topBlocks_.length==1){
var blockType = editor_blockly.workspace.topBlocks_[0].type;
if(blockType!==eventType+'_m' && !(editor_blockly.isCommonEntry() && blockType == 'common_m')){
editor_blockly.setValue('入口方块类型错误');
return;
}
}
try {
var code = Blockly.JavaScript.workspaceToCode(workspace).replace(/\\(i|c|d|e|g|z)/g, '\\\\$1');
editor_blockly.setValue(code);
} catch (error) {
editor_blockly.setValue(String(error));
if (error instanceof OmitedError){
var blockName = error.blockName;
var varName = error.varName;
var block = error.block;
}
// console.log(error);
}
}
workspace.addChangeListener(omitedcheckUpdateFunction);
workspace.addChangeListener(Blockly.Events.disableOrphans);
editor_blockly.workspace = workspace;
MotaActionFunctions.workspace = function(){
return editor_blockly.workspace;
}
// 因为在editor_blockly.parse里已经HTML转义过一次了,所以这里要覆盖掉以避免在注释中出现&lt;等
MotaActionFunctions.xmlText = function (ruleName,inputs,isShadow,comment,collapsed,disabled) {
var rule = MotaActionBlocks[ruleName];
var blocktext = isShadow?'shadow':'block';
var xmlText = [];
xmlText.push('<'+blocktext+' type="'+ruleName+'"'+(collapsed ? ' collapsed="true"' : '')+(disabled ? ' disabled="true"' : '')+'>');
if(!inputs)inputs=[];
for (var ii=0,inputType;inputType=rule.argsType[ii];ii++) {
var input = inputs[ii];
var _input = '';
var noinput = (input===null || input===undefined);
if(noinput && inputType==='field' && MotaActionBlocks[rule.argsGrammarName[ii]].type!=='field_dropdown') continue;
if(noinput && inputType==='field') {
noinput = false;
input = rule.fieldDefault(rule.args[ii])
}
if(noinput) input = '';
if(inputType==='field' && MotaActionBlocks[rule.argsGrammarName[ii]].type==='field_checkbox')input=input?'TRUE':'FALSE';
if(inputType!=='field') {
var subList = false;
var subrulename = rule.argsGrammarName[ii];
var subrule = MotaActionBlocks[subrulename];
if (subrule instanceof Array) {
subrulename=subrule[subrule.length-1];
subrule = MotaActionBlocks[subrulename];
subList = true;
}
_input = subrule.xmlText([],true);
if(noinput && !subList && !isShadow) {
//无输入的默认行为是: 如果语句块的备选方块只有一个,直接代入方块
input = subrule.xmlText();
}
}
xmlText.push('<'+inputType+' name="'+rule.args[ii]+'">');
xmlText.push(_input+input);
xmlText.push('</'+inputType+'>');
}
if(comment){
xmlText.push('<comment>');
xmlText.push(comment);
xmlText.push('</comment>');
}
var next = inputs[rule.args.length];
if (next) {//next
xmlText.push('<next>');
xmlText.push(next);
xmlText.push('</next>');
}
xmlText.push('</'+blocktext+'>');
return xmlText.join('');
}
})();
// end mark sfergsvae
}).toString().split('// start mark sfergsvae')[1].split('// end mark sfergsvae')[0]

52
_server/editor_config.js Normal file
View File

@ -0,0 +1,52 @@
function editor_config() {
this.address = "_server/config.json";
this._isWriting = false;
}
editor_config.prototype.load = function(callback) {
var _this = this;
fs.readFile(this.address, "utf-8", function(e, d) {
if (e) {
console.error("无法读取配置文件, 已重新生成");
_this.config = {};
_this.save(callback);
} else {
try {
_this.config = JSON.parse(d);
if (callback) callback();
} catch (e) {
console.error(e);
_this.config = {};
_this.save(callback);
}
}
});
}
editor_config.prototype.get = function(key, defaultValue) {
value = this.config[key];
return value != null ? value : defaultValue;
}
editor_config.prototype.set = function(key, value, callback) {
this.config[key] = value;
if (callback !== false) this.save(callback);
}
editor_config.prototype.save = function(callback) {
// 读写锁防止写文件冲突
if (this._isWriting) return;
try {
this._isWriting = true;
var _this = this;
fs.writeFile(this.address, JSON.stringify(this.config) ,'utf-8', function(e) {
_this._isWriting = false;
if (e) console.error("写入配置文件失败");
if (callback instanceof Function) callback();
})
} catch (e) {
this._isWriting = false;
console.error(e);
if (callback instanceof Function) callback();
}
}

1228
_server/editor_datapanel.js Normal file

File diff suppressed because it is too large Load Diff

1118
_server/editor_file.js Normal file

File diff suppressed because it is too large Load Diff

199
_server/editor_game.js Normal file
View File

@ -0,0 +1,199 @@
editor_game_wrapper = function (editor, main, core) {
// 原则上重构后只有此文件允许`\s(main|core)`形式的调用, 以及其初始化 editor_game_wrapper(editor, main, core)
editor_game = function () {
this.replacerRecord = {}
}
//////////////////// 修改数据相关 ////////////////////
// 三个 replacer 和 replacerRecord 暂时放在此处
editor_game.prototype.replacerForLoading = function (_key, value) {
var rmap = editor.game.replacerRecord;
if (value instanceof Function) {
var guid_ = editor.util.guid()
rmap[guid_] = value.toString()
return guid_
} else if (value === null) {
// 为了包含plugins的新建
var guid_ = editor.util.guid()
rmap[guid_] = null
return guid_
}
return value
}
editor_game.prototype.replacerForSaving = function (_key, value) {
var rmap = editor.game.replacerRecord;
if (rmap.hasOwnProperty(value)) {
return rmap[value]
}
return value
}
editor_game.prototype.getValue = function (field) {
var rmap = editor.game.replacerRecord;
var value = eval(field)
if (rmap.hasOwnProperty(oldval)) {
return rmap[value]
} else {
return value
}
}
editor_game.prototype.setValue = function (field, value) {
var rmap = editor.game.replacerRecord;
var oldval = eval(field)
if (rmap.hasOwnProperty(oldval)) {
rmap[value] = eval(value)
} else {
eval(field + '=' + value)
}
}
editor_game.prototype.replacerWithoutRecord = function (_key, value) {
if (value instanceof Function) {
return value.toString()
} else return value
}
editor_game.prototype.fixFunctionInGameData = function () {
var rf = editor.game.replacerWithoutRecord
core.floors = JSON.parse(JSON.stringify(core.floors, rf));
core.data = JSON.parse(JSON.stringify(core.data, rf));
data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = JSON.parse(JSON.stringify(data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d, rf));
}
//////////////////// 加载游戏数据相关 ////////////////////
// 初始化数字与地图图块的对应
editor_game.prototype.idsInit = function (maps, icons) {
editor.ids = [0];
editor.indexs = [];
var MAX_NUM = 0;
var keys = Object.keys(maps_90f36752_8815_4be8_b32b_d7fad1d0542e);
for (var ii = 0; ii < keys.length; ii++) {
var v = ~~keys[ii];
if (v > MAX_NUM && v < core.icons.tilesetStartOffset) MAX_NUM = v;
}
editor.MAX_NUM = MAX_NUM;
var getInfoById = function (id) {
var block = maps.initBlock(0, 0, id);
if (Object.prototype.hasOwnProperty.call(block, 'event')) {
return block;
}
}
var point = 0;
for (var i = 0; i <= MAX_NUM; i++) {
var indexBlock = getInfoById(i);
editor.indexs[i] = [];
if (indexBlock) {
var id = indexBlock.event.id;
var indexId = indexBlock.id;
var allCls = Object.keys(icons);
if (i == 17) {
editor.ids.push({ 'idnum': 17, 'id': id, 'images': 'terrains' });
point++;
editor.indexs[i].push(point);
continue;
}
for (var j = 0; j < allCls.length; j++) {
if (id in icons[allCls[j]]) {
editor.ids.push({ 'idnum': indexId, 'id': id, 'images': allCls[j], 'y': icons[allCls[j]][id] });
point++;
editor.indexs[i].push(point);
}
}
}
}
editor.indexs[0] = [0];
var startOffset = core.icons.tilesetStartOffset;
for (var i in core.tilesets) {
var imgName = core.tilesets[i];
var img = core.material.images.tilesets[imgName];
var width = Math.floor(img.width / 32), height = Math.floor(img.height / 32);
if (img.width % 32 || img.height % 32) {
// alert(imgName + '的长或宽不是32的整数倍, 请修改后刷新页面');
console.warn(imgName + '的长或宽不是32的整数倍, 请修改后刷新页面');
}
if (img.width * img.height > 32 * 32 * 3000) {
// alert(imgName + '上的图块数量超过了3000请修改后刷新页面');
console.warn(imgName + '上的图块数量超过了3000请修改后刷新页面');
}
for (var id = startOffset; id < startOffset + width * height; id++) {
var x = (id - startOffset) % width, y = parseInt((id - startOffset) / width);
var indexBlock = getInfoById(id);
editor.ids.push({ 'idnum': id, 'id': indexBlock.event.id, 'images': imgName, "x": x, "y": y, isTile: true });
point++;
editor.indexs[id] = [point];
}
startOffset += core.icons.tilesetStartOffset;
}
}
// 获取当前地图
editor_game.prototype.fetchMapFromCore = function () {
var mapArray = core.getMapArray(core.status.floorId);
editor.map = mapArray.map(function (v) {
return v.map(function (v) {
var x = parseInt(v), y = editor.indexs[x];
if (y == null) {
printe("素材数字" + x + "未定义。是不是忘了注册或者接档时没有覆盖icons.js和maps.js");
y = [0];
}
return editor.ids[y[0]]
})
});
editor.currentFloorId = core.status.floorId;
editor.currentFloorData = core.floors[core.status.floorId];
// 补出缺省的数据
editor.currentFloorData.autoEvent = editor.currentFloorData.autoEvent || {};
//
for (var ii = 0, name; name = editor.dom.canvas[ii]; ii++) {
name += 'map';
var mapArray = editor.currentFloorData[name];
if (!mapArray || JSON.stringify(mapArray) == JSON.stringify([])) {//未设置或空数组
//与editor.map同形的全0
mapArray = eval('[' + Array(editor.map.length + 1).join('[' + Array(editor.map[0].length + 1).join('0,') + '],') + ']');
}
mapArray = core.maps._processInvalidMap(mapArray, editor.map[0].length, editor.map.length);
editor[name] = mapArray.map(function (v) {
return v.map(function (v) {
var x = parseInt(v), y = editor.indexs[x];
if (y == null) {
printe("素材数字" + x + "未定义。是不是忘了注册或者接档时没有覆盖icons.js和maps.js");
y = [0];
}
return editor.ids[y[0]]
})
});
}
}
// 获取地图列表
editor_game.prototype.getFloorFileList = function (callback) {
// callback([Array<String>,err:String])
editor.util.checkCallback(callback);
/* editor.fs.readdir('project/floors',function(err, data){
callback([data,err]);
}); */
callback([editor.core.floorIds, null]);
}
editor_game.prototype.doCoreFunc = function (funcname) {
return core[funcname].apply(core, Array.prototype.slice.call(arguments, 1));
}
editor_game.prototype.getEnemy = function (id) {
return core.material.enemys[id];
}
editor_game.prototype.getFirstData = function () {
return core.firstData;
}
editor.constructor.prototype.game = new editor_game();
}
//editor_game_wrapper(editor);

193
_server/editor_listen.js Normal file
View File

@ -0,0 +1,193 @@
editor_listen_wrapper = function (editor) {
editor.constructor.prototype.listen = function () {
editor.dom.body.onmousedown = editor.uifunctions.body_click;
editor.dom.eui.oncontextmenu = function (e) { e.preventDefault() } // 自定义了右键菜单, 阻止默认行为
editor.dom.midMenu.oncontextmenu = function (e) { e.preventDefault() }
editor.dom.eui.ondblclick = editor.uifunctions.map_doubleClick
editor.dom.eui.onmousedown = editor.uifunctions.map_ondown
editor.dom.eui.onmousemove = editor.uifunctions.map_onmove
editor.dom.eui.onmouseup = editor.uifunctions.map_onup
editor.dom.eui.onmouseout = editor.uifunctions.map_onmoveout
editor.dom.mid.onmousewheel = editor.uifunctions.map_mousewheel
editor.uivalues.shortcut = editor.config.get('shortcut', { 48: 0, 49: 0, 50: 0, 51: 0, 52: 0, 53: 0, 54: 0, 55: 0, 56: 0, 57: 0 });
editor.dom.body.onkeydown = editor.uifunctions.body_shortcut
editor.uivalues.scrollBarHeight = editor.uifunctions.getScrollBarHeight();
editor.dom.iconExpandBtn.style.display = 'block';
editor.dom.iconExpandBtn.innerText = editor.uivalues.folded ? "展开素材区" : "折叠素材区";
editor.dom.iconExpandBtn.onclick = editor.uifunctions.fold_material_click
editor.dom.iconLib.onmousedown = editor.uifunctions.material_ondown
editor.dom.iconLib.onmousemove = editor.uifunctions.material_onmove
editor.dom.iconLib.onmouseup = editor.uifunctions.material_onup
editor.dom.iconLib.oncontextmenu = function (e) { e.preventDefault() }
editor.dom.extraEvent.onmouseup = editor.uifunctions.extraEvent_click
editor.dom.chooseThis.onmouseup = editor.uifunctions.chooseThis_click
editor.dom.chooseInRight.onmouseup = editor.uifunctions.chooseInRight_click
editor.dom.copyLoc.onmouseup = editor.uifunctions.copyLoc_click
editor.dom.pasteLoc.onmouseup = editor.uifunctions.pasteLoc_click
editor.dom.clearEvent.onmouseup = editor.uifunctions.clearEvent_click
editor.dom.clearLoc.onmouseup = editor.uifunctions.clearLoc_click
editor.dom.undoFloor.onclick = editor.uifunctions.undoFloor_click
editor.dom.selectFloorBtn.onclick = editor.uifunctions.selectFloorBtn_click
editor.dom.editorTheme.onchange = editor.uifunctions.editorTheme_onchange
editor.dom.lastUsed.onmouseup = editor.uifunctions.lastUsed_click;
editor.dom.lastUsed.oncontextmenu = function (e) { e.preventDefault(); }
editor.dom.clearLastUsedBtn.onclick = editor.uifunctions.clearLastUsedBtn_click;
editor.dom.showMovable.onchange = editor.uifunctions.showMovable_onchange;
editor.dom.brushMod.onchange = editor.uifunctions.brushMod_onchange
if (editor.dom.brushMod2) editor.dom.brushMod2.onchange = editor.uifunctions.brushMod2_onchange;
if (editor.dom.brushMod3) editor.dom.brushMod3.onchange = editor.uifunctions.brushMod3_onchange;
if (editor.dom.brushMod4) editor.dom.brushMod4.onchange = editor.uifunctions.brushMod4_onchange;
editor.dom.layerMod.onchange = editor.uifunctions.layerMod_onchange
if (editor.dom.layerMod2) editor.dom.layerMod2.onchange = editor.uifunctions.layerMod2_onchange;
if (editor.dom.layerMod3) editor.dom.layerMod3.onchange = editor.uifunctions.layerMod3_onchange;
editor.uifunctions.viewportButtons_func()
window.onbeforeunload = function () {
var saveFloor = document.getElementById('saveFloor');
if (saveFloor && saveFloor.classList.contains('highlight')) {
return '你尚未保存地图,确定退出么?';
}
return null;
}
}
editor.constructor.prototype.mobile_listen = function () {
if (!editor.isMobile) return;
var mobileview = document.getElementById('mobileview');
var mid = document.getElementById('mid');
var right = document.getElementById('right');
// var mobileeditdata = document.getElementById('mobileeditdata');
editor.showdataarea = function (callShowMode) {
mid.style = 'z-index:-1;opacity: 0;';
right.style = 'z-index:-1;opacity: 0;';
// mobileeditdata.style = '';
if (callShowMode) editor.mode.showMode(editor.dom.editModeSelect.value);
editor.uifunctions.hideMidMenu();
}
mobileview.children[0].onclick = function () {
editor.showdataarea(true)
}
mobileview.children[1].onclick = function () {
mid.style = 'z-index:110';
right.style = 'z-index:-1;opacity: 0;';
// mobileeditdata.style = 'z-index:-1;opacity: 0;';
editor.lastClickId = '';
}
mobileview.children[3].onclick = function () {
mid.style = 'z-index:-1;opacity: 0;';
right.style = 'z-index:110';
// mobileeditdata.style = 'z-index:-1;opacity: 0;';
editor.lastClickId = '';
}
/*
var gettrbyid = function () {
if (!editor.lastClickId) return false;
thisTr = document.getElementById(editor.lastClickId);
input = thisTr.children[2].children[0].children[0];
field = thisTr.children[0].getAttribute('title');
cobj = JSON.parse(thisTr.children[1].getAttribute('cobj'));
return [thisTr, input, field, cobj];
}
mobileeditdata.children[0].onclick = function () {
var info = gettrbyid()
if (!info) return;
info[1].ondblclick()
}
mobileeditdata.children[1].onclick = function () {
var info = gettrbyid()
if (!info) return;
printf(info[2])
}
mobileeditdata.children[2].onclick = function () {
var info = gettrbyid()
if (!info) return;
printf(info[0].children[1].getAttribute('title'))
}
*/
//=====
document.body.ontouchstart = document.body.onmousedown;
document.body.onmousedown = null;
editor.dom.eui.ontouchstart = editor.dom.eui.onmousedown
editor.dom.eui.onmousedown = null
editor.dom.eui.ontouchmove = editor.dom.eui.onmousemove
editor.dom.eui.onmousemove = null
editor.dom.eui.ontouchend = editor.dom.eui.onmouseup
editor.dom.eui.onmouseup = null
editor.dom.chooseThis.ontouchstart = editor.dom.chooseThis.onmousedown
editor.dom.chooseThis.onmousedown = null
editor.dom.chooseInRight.ontouchstart = editor.dom.chooseInRight.onmousedown
editor.dom.chooseInRight.onmousedown = null
editor.dom.copyLoc.ontouchstart = editor.dom.copyLoc.onmousedown
editor.dom.copyLoc.onmousedown = null
editor.dom.pasteLoc.ontouchstart = editor.dom.pasteLoc.onmousedown
editor.dom.pasteLoc.onmousedown = null
editor.dom.clearLoc.ontouchstart = editor.dom.clearLoc.onmousedown
editor.dom.clearLoc.onmousedown = null
// 不使用以下6语句, 会使得素材区手机无法拖动, 手机的框选素材只能放弃, 要通过弹框实现框选
// editor.dom.iconLib.ontouchstart = editor.dom.iconLib.onmousedown
// editor.dom.iconLib.onmousedown = null
// editor.dom.iconLib.ontouchmove = editor.dom.iconLib.onmousemove
// editor.dom.iconLib.onmousemove = null
// editor.dom.iconLib.ontouchend = editor.dom.iconLib.onmouseup
// editor.dom.iconLib.onmouseup = null
}
editor.constructor.prototype.mode_listen = function (callback) {
// 这里的函数还没有写jsdoc, 通过_func()的方式先完成分类
editor.uifunctions.newIdIdnum_func()
editor.uifunctions.changeId_func()
editor.uifunctions.copyPasteEnemyItem_func();
editor.uifunctions.selectFloor_func()
editor.uifunctions.saveFloor_func()
editor.uifunctions.openDoc_func();
editor.uifunctions.newMap_func()
editor.uifunctions.createNewMaps_func()
editor.uifunctions.changeFloorId_func()
editor.uifunctions.changeFloorSize_func()
// editor.uifunctions.fixCtx_func()
editor.uifunctions.appendPic_func();
/*
editor.uifunctions.selectAppend_func()
editor.uifunctions.selectFileBtn_func()
editor.uifunctions.changeColorInput_func()
editor.uifunctions.picClick_func()
editor.uifunctions.appendConfirm_func()
*/
editor.dom.editModeSelect.onchange = editor.mode.editModeSelect_onchange
if (Boolean(callback)) callback();
}
}

1190
_server/editor_mappanel.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,243 @@
editor_materialpanel_wrapper = function (editor) {
// 由于历史遗留原因, 以下变量作为全局变量使用
// selectBox
window.selectBox=document.getElementById('selectBox')
selectBox._isSelected=false
selectBox.isSelected=function(value){
if(value!=null){
selectBox._isSelected=value;
editor.dom.dataSelection.style.display=value?'':'none'
}
return selectBox._isSelected
}
var locToPos = function (loc) {
return { 'x': ~~(loc.x / loc.size), 'y': ~~(loc.y / loc.size) };
}
editor.uifunctions.getScrollBarHeight = function () {
var outer = document.createElement("div");
outer.style.visibility = "hidden";
outer.style.width = "100px";
outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps
document.body.appendChild(outer);
var widthNoScroll = outer.offsetWidth;
// force scrollbars
outer.style.overflow = "scroll";
// add innerdiv
var inner = document.createElement("div");
inner.style.width = "100%";
outer.appendChild(inner);
var widthWithScroll = inner.offsetWidth;
// remove divs
outer.parentNode.removeChild(outer);
return widthNoScroll - widthWithScroll;
}
/**
* editor.dom.iconExpandBtn.onclick
*/
editor.uifunctions.fold_material_click = function () {
if (editor.uivalues.folded) {
if (confirm("你想要展开素材吗?\n展开模式下将显示全素材内容。")) {
editor.config.set('folded', false, function() {
window.location.reload();
});
}
} else {
var perCol = parseInt(prompt("请输入折叠素材模式下每列的个数:", "50")) || 0;
if (perCol > 0) {
editor.config.set('foldPerCol', perCol, false);
editor.config.set('folded', true, function() {
window.location.reload();
});
}
}
}
/**
* editor.dom.iconLib.onmousedown
* 素材区的单击/拖拽事件
*/
editor.uifunctions.material_ondown = function (e) {
e.stopPropagation();
e.preventDefault();
editor.uivalues.lastMoveMaterE=e;
if (!editor.isMobile && e.clientY >= editor.dom.iconLib.offsetHeight - editor.uivalues.scrollBarHeight) return;
var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
editor.uivalues.startLoc={
'x': scrollLeft + e.clientX + editor.dom.iconLib.scrollLeft - right.offsetLeft - editor.dom.iconLib.offsetLeft,
'y': scrollTop + e.clientY + editor.dom.iconLib.scrollTop - right.offsetTop - editor.dom.iconLib.offsetTop,
'px': e.clientX,
'py': e.clientY,
'size': 32
};
}
/**
* editor.dom.iconLib.onmousemove
* 素材区的单击/拖拽事件
*/
editor.uifunctions.material_onmove = function (e) {
e.stopPropagation();
e.preventDefault();
editor.uivalues.lastMoveMaterE=e;
if (!editor.uivalues.startLoc) return;
var pos0 = locToPos(editor.uivalues.startLoc);
editor.dom.dataSelection.style.left = 32 * pos0.x + 'px';
editor.dom.dataSelection.style.top = 32 * pos0.y + 'px';
editor.dom.dataSelection.style.width = e.clientX - editor.uivalues.startLoc.px + 'px';
editor.dom.dataSelection.style.height = e.clientY - editor.uivalues.startLoc.py + 'px';
editor.dom.dataSelection.style.display = 'block';
}
/**
* editor.dom.iconLib.onmouseup
* 素材区的单击/拖拽事件
*/
editor.uifunctions.material_onup = function (ee) {
var startLoc = editor.uivalues.startLoc;
editor.uivalues.startLoc = null;
var e=editor.uivalues.lastMoveMaterE;
if (!editor.isMobile && e.clientY >= editor.dom.iconLib.offsetHeight - editor.uivalues.scrollBarHeight) return;
var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
var loc = {
'x': scrollLeft + e.clientX + editor.dom.iconLib.scrollLeft - right.offsetLeft - editor.dom.iconLib.offsetLeft,
'y': scrollTop + e.clientY + editor.dom.iconLib.scrollTop - right.offsetTop - editor.dom.iconLib.offsetTop,
'size': 32
};
editor.loc = loc;
editor.uivalues.tileSize = [1,1];
var pos0 = locToPos(startLoc);
var pos = locToPos(loc);
for (var spriter in editor.widthsX) {
if (pos.x >= editor.widthsX[spriter][1] && pos.x < editor.widthsX[spriter][2]) {
var ysize = spriter.endsWith('48') ? 48 : 32;
loc.ysize = ysize;
pos.images = editor.widthsX[spriter][0];
pos.y = ~~(loc.y / loc.ysize);
if (!editor.uivalues.folded && core.tilesets.indexOf(pos.images) == -1) pos.x = editor.widthsX[spriter][1];
var autotiles = core.material.images['autotile'];
if (pos.images == 'autotile') {
var imNames = Object.keys(autotiles);
if (editor.uivalues.folded) {
pos.y = Math.min(pos.y, imNames.length - 1);
pos.images = imNames[pos.y];
} else {
if ((pos.y + 1) * ysize > editor.widthsX[spriter][3])
pos.y = ~~(editor.widthsX[spriter][3] / ysize) - 4;
else {
for (var i = 0; i < imNames.length; i++) {
if (pos.y >= 4 * i && pos.y < 4 * (i + 1)) {
pos.images = imNames[i];
pos.y = 4 * i;
}
}
}
}
}
else {
var height = editor.widthsX[spriter][3], col = height / ysize;
if (spriter == 'terrains') col += 2;
if (editor.uivalues.folded && core.tilesets.indexOf(pos.images) == -1) {
col = (pos.x == editor.widthsX[spriter][2] - 1) ? ((col - 1) % editor.uivalues.foldPerCol + 1) : editor.uivalues.foldPerCol;
}
pos.y = Math.min(pos.y, col - 1);
}
selectBox.isSelected(true);
// console.log(pos,core.material.images[pos.images].height)
editor.dom.dataSelection.style.left = pos.x * 32 + 'px';
editor.dom.dataSelection.style.top = pos.y * ysize + 'px';
editor.dom.dataSelection.style.height = ysize - 6 + 'px';
editor.dom.dataSelection.style.width = 32 - 6 + 'px';
if (pos.x == 0 && pos.y == 0) {
// editor.info={idnum:0, id:'empty','images':'清除块', 'y':0};
editor.info = 0;
} else if (pos.x == 0 && pos.y == 1) {
editor.info = editor.ids[editor.indexs[17]];
} else {
if (autotiles[pos.images]) editor.info = { 'images': pos.images, 'y': 0 };
else if (core.tilesets.indexOf(pos.images) != -1) editor.info = { 'images': pos.images, 'y': pos.y, 'x': pos.x - editor.widthsX[spriter][1] };
else {
var y = pos.y;
if (editor.uivalues.folded) {
y += editor.uivalues.foldPerCol * (pos.x - editor.widthsX[spriter][1]);
}
if (pos.images == 'terrains') y -= 2;
editor.info = { 'images': pos.images, 'y': y }
}
for (var idindex = 0; idindex < editor.ids.length; idindex++) {
if ((core.tilesets.indexOf(pos.images) != -1 && editor.info.images == editor.ids[idindex].images
&& editor.info.y == editor.ids[idindex].y && editor.info.x == editor.ids[idindex].x)
|| (Object.prototype.hasOwnProperty.call(autotiles, pos.images) && editor.info.images == editor.ids[idindex].id
&& editor.info.y == editor.ids[idindex].y)
|| (core.tilesets.indexOf(pos.images) == -1 && editor.info.images == editor.ids[idindex].images
&& editor.info.y == editor.ids[idindex].y)
) {
editor.info = editor.ids[idindex];
break;
}
}
if (editor.info.isTile && (editor.isMobile || e.button == 2)) { //这段改一改之类的应该能给手机用,就不删了
var v = prompt("请输入该额外素材区域绑定宽高,以逗号分隔", "1,1");
if (v != null && /^\d+,\d+$/.test(v)) {
v = v.split(",");
var x = parseInt(v[0]), y = parseInt(v[1]);
var widthX = editor.widthsX[editor.info.images];
if (x <= 0 || y <= 0 || editor.info.x + x > widthX[2] - widthX[1] || 32*(editor.info.y + y) > widthX[3]) {
alert("不合法的输入范围,已经越界");
} else {
editor.uivalues.tileSize = [x, y];
editor.dom.dataSelection.style.left = pos.x * 32 + 'px';
editor.dom.dataSelection.style.top = pos.y * ysize + 'px';
editor.dom.dataSelection.style.height = ysize*y - 6 + 'px';
editor.dom.dataSelection.style.width = 32*x - 6 + 'px';
}
}
}
if (editor.info.isTile && !editor.isMobile && e.button != 2) { //左键拖拽框选
var x = pos.x-pos0.x+1, y = pos.y-pos0.y+1;
var widthX = editor.widthsX[editor.info.images];
// 懒得仔细处理了, 只允许左上往右下拉
if (x <= 0 || y <= 0 || pos0.x < widthX[1]){
} else {
editor.info = editor.ids[idindex-(x-1)-(y-1)*(widthX[2]-widthX[1])];
editor.uivalues.tileSize = [x, y];
editor.dom.dataSelection.style.left = pos0.x * 32 + 'px';
editor.dom.dataSelection.style.top = pos0.y * ysize + 'px';
editor.dom.dataSelection.style.height = ysize*y - 6 + 'px';
editor.dom.dataSelection.style.width = 32*x - 6 + 'px';
}
}
}
editor.uifunctions.showBlockInfo(JSON.parse(JSON.stringify(editor.info)));
editor_mode.onmode('nextChange');
editor_mode.onmode('enemyitem');
editor.updateLastUsedMap();
//editor_mode.enemyitem();
}
}
}
}

371
_server/editor_mode.js Normal file
View File

@ -0,0 +1,371 @@
editor_mode = function (editor) {
var core = editor.core;
function editor_mode() {
this.ids = {
'loc': 'left2',
'enemyitem': 'left3',
'floor': 'left4',
'tower': 'left5',
'functions': 'left8',
'map': 'left',
'appendpic': 'left1',
'commonevent': 'left9',
'plugins': 'left10',
}
this._ids = {}
this.dom = {}
this.actionList = [];
this.mode = 'tower'; // 初始默认显示全塔属性
this.info = {};
this.appendPic = {};
this.doubleClickMode = 'change';
}
editor_mode.prototype.init = function (callback) {
if (Boolean(callback)) callback();
}
editor_mode.prototype.init_dom_ids = function (callback) {
Object.keys(editor_mode.ids).forEach(function (v) {
editor_mode.dom[v] = document.getElementById(editor_mode.ids[v]);
editor_mode._ids[editor_mode.ids[v]] = v;
});
if (Boolean(callback)) callback();
}
editor_mode.prototype.indent = function (field) {
var num = '\t';
if (field.indexOf("['main']") === 0) return 0;
if (field === "['special']") return 0;
return num;
}
editor_mode.prototype.addAction = function (action) {
editor_mode.actionList.push(action);
}
editor_mode.prototype.doActionList = function (mode, actionList, callback) {
if (actionList.length == 0) return;
printf('修改中...');
var cb = function (objs_) {
if (objs_.slice(-1)[0] != null) {
printe(objs_.slice(-1)[0]);
throw (objs_.slice(-1)[0])
}
;
var str = '修改成功!';
if (data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.name == 'template')
str += '<br/>请注意全塔属性的name尚未修改请及时予以设置。';
if (mode == 'enemyitem') {
if (editor.info && editor.info.idnum) {
var block = editor.core.maps.blocksInfo[editor.info.idnum];
if (block.doorInfo != null && block.doorInfo.keys != null && Object.keys(block.doorInfo.keys).length > 0
&& block.trigger != 'openDoor') {
str += "<br/>你修改了门信息但触发器未改成openDoor请修改否则无法撞击开门。"
}
}
if (editor_mode.info.images == 'enemys' || editor_mode.info.images == 'enemy48') {
if (core.getFaceDownId(editor_mode.info.id) != editor_mode.info.id) {
str += "<br/>绑定行走图朝向后只需要对应设置朝下怪物的属性,会自动同步而无需修改其他朝向的属性。"
}
}
}
printf(str);
if (callback) callback();
}
switch (mode) {
case 'loc':
editor.file.editLoc(editor_mode.pos.x, editor_mode.pos.y, actionList, function (objs_) {
cb(objs_);
editor.drawPosSelection();
});
break;
case 'enemyitem':
if (editor_mode.info.images == 'enemys' || editor_mode.info.images == 'enemy48') {
editor.file.editEnemy(editor_mode.info.id, actionList, cb);
} else if (editor_mode.info.images == 'items') {
editor.file.editItem(editor_mode.info.id, actionList, cb);
} else {
editor.file.editMapBlocksInfo(editor_mode.info.idnum, actionList, cb);
}
break;
case 'floor':
editor.file.editFloor(actionList, cb);
break;
case 'tower':
editor.file.editTower(actionList, cb);
break;
case 'functions':
editor.file.editFunctions(actionList, cb);
break;
case 'commonevent':
editor.file.editCommonEvent(actionList, cb);
break;
case 'plugins':
editor.file.editPlugins(actionList, cb);
break;
default:
break;
}
}
editor_mode.prototype.onmode = function (mode, callback) {
if (editor_mode.mode != mode) {
if (mode === 'save') editor_mode.doActionList(editor_mode.mode, editor_mode.actionList, callback);
if (editor_mode.mode === 'nextChange' && mode) editor_mode.showMode(mode);
if (mode !== 'save') editor_mode.mode = mode;
editor_mode.actionList = [];
}
}
editor_mode.prototype.showMode = function (mode) {
for (var name in this.dom) {
editor_mode.dom[name].style = 'z-index:-1;opacity: 0;';
}
editor_mode.dom[mode].style = '';
editor_mode.doubleClickMode = 'change';
// clear
editor.drawEventBlock();
if (editor_mode[mode]) editor_mode[mode]();
editor.dom.editModeSelect.value = mode;
if (!selectBox.isSelected()) editor.uifunctions.showTips();
}
editor_mode.prototype.change = function (value) {
editor_mode.onmode('nextChange');
editor_mode.onmode(value);
if (editor.isMobile) editor.showdataarea(false);
}
editor_mode.prototype.checkUnique = function (thiseval) {
if (!(thiseval instanceof Array)) return false;
var map = {};
for (var i = 0; i < thiseval.length; ++i) {
if (map[thiseval[i]]) {
alert("警告:存在重复定义!");
return false;
}
map[thiseval[i]] = true;
}
return true;
}
editor_mode.prototype.checkFloorIds = function (thiseval) {
if (!editor_mode.checkUnique(thiseval)) return false;
var oldvalue = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.main.floorIds;
fs.readdir('project/floors', function (err, data) {
if (err) {
printe(err);
throw Error(err);
}
var newfiles = thiseval.map(function (v) { return v + '.js' });
var notExist = '';
for (var name, ii = 0; name = newfiles[ii]; ii++) {
if (data.indexOf(name) === -1) notExist = name;
}
if (notExist) {
var discard = confirm('文件' + notExist + '不存在, 保存会导致工程无法打开, 是否放弃更改');
if (discard) {
editor.file.editTower([['change', "['main']['floorIds']", oldvalue]], function (objs_) {//console.log(objs_);
if (objs_.slice(-1)[0] != null) {
printe(objs_.slice(-1)[0]);
throw (objs_.slice(-1)[0])
}
; printe('已放弃floorIds的修改请F5进行刷新');
});
}
}
});
return true
}
editor_mode.prototype.checkImages = function (thiseval, directory) {
if (!directory) return true;
if (!editor_mode.checkUnique(thiseval)) return false;
fs.readdir(directory, function (err, data) {
if (err) {
printe(err);
throw Error(err);
}
var notExist = null;
thiseval.map(function (v) {
var name = v.indexOf('.') < 0 ? (v+'.png') : v;
if (data.indexOf(name) < 0) notExist = name;
return name;
});
if (notExist) {
alert('警告!图片' + notExist + '不存在!保存可能导致工程无法打开,请及时修改!');
}
});
return true;
}
editor_mode.prototype.changeDoubleClickModeByButton = function (mode) {
({
delete: function () {
printf('下一次双击表格的项删除,切换下拉菜单可取消;编辑后需刷新浏览器生效。');
editor_mode.doubleClickMode = mode;
},
add: function () {
printf('下一次双击表格的项则在同级添加新项,切换下拉菜单可取消;编辑后需刷新浏览器生效。');
editor_mode.doubleClickMode = mode;
}
}[mode])();
}
/////////////////////////////////////////////////////////////////////////////
editor_mode.prototype.loc = function (callback) {
//editor.pos={x: 0, y: 0};
if (!core.isset(editor.pos)) return;
editor_mode.pos = editor.pos;
document.getElementById('pos_a6771a78_a099_417c_828f_0a24851ebfce').innerText = editor_mode.pos.x + ',' + editor_mode.pos.y;
var objs = [];
editor.file.editLoc(editor_mode.pos.x, editor_mode.pos.y, [], function (objs_) {
objs = objs_;
//console.log(objs_)
});
//只查询不修改时,内部实现不是异步的,所以可以这么写
var tableinfo = editor.table.objToTable(objs[0], objs[1]);
document.getElementById('table_3d846fc4_7644_44d1_aa04_433d266a73df').innerHTML = tableinfo.HTML;
tableinfo.listen(tableinfo.guids);
editor.drawPosSelection();
if (Boolean(callback)) callback();
}
editor_mode.prototype.enemyitem = function (callback) {
//editor.info=editor.ids[editor.indexs[201]];
if (!core.isset(editor.info)) return;
if (Object.keys(editor.info).length !== 0 && editor.info.idnum != 17) editor_mode.info = editor.info;//避免editor.info被清空导致无法获得是物品还是怪物
if (!core.isset(editor_mode.info.id)) {
// document.getElementById('table_a3f03d4c_55b8_4ef6_b362_b345783acd72').innerHTML = '';
document.getElementById('newIdIdnum').style.display = 'block';
document.getElementById('enemyItemTable').style.display = 'none';
document.getElementById('changeId').style.display = 'none';
return;
}
document.getElementById('newIdIdnum').style.display = 'none';
document.getElementById('enemyItemTable').style.display = 'block';
document.getElementById('changeId').style.display = 'block';
var objs = [];
if (editor_mode.info.images == 'enemys' || editor_mode.info.images == 'enemy48') {
editor.file.editEnemy(editor_mode.info.id, [], function (objs_) {
objs = objs_;
//console.log(objs_)
});
} else if (editor_mode.info.images == 'items') {
editor.file.editItem(editor_mode.info.id, [], function (objs_) {
objs = objs_;
//console.log(objs_)
});
} else {
/* document.getElementById('table_a3f03d4c_55b8_4ef6_b362_b345783acd72').innerHTML='';
return; */
editor.file.editMapBlocksInfo(editor_mode.info.idnum, [], function (objs_) {
objs = objs_;
//console.log(objs_)
});
}
//只查询不修改时,内部实现不是异步的,所以可以这么写
var tableinfo = editor.table.objToTable(objs[0], objs[1]);
document.getElementById('table_a3f03d4c_55b8_4ef6_b362_b345783acd72').innerHTML = tableinfo.HTML;
tableinfo.listen(tableinfo.guids);
if (Boolean(callback)) callback();
}
editor_mode.prototype.floor = function (callback) {
var objs = [];
editor.file.editFloor([], function (objs_) {
objs = objs_;
//console.log(objs_)
});
//只查询不修改时,内部实现不是异步的,所以可以这么写
var tableinfo = editor.table.objToTable(objs[0], objs[1]);
document.getElementById('table_4a3b1b09_b2fb_4bdf_b9ab_9f4cdac14c74').innerHTML = tableinfo.HTML;
tableinfo.listen(tableinfo.guids);
if (Boolean(callback)) callback();
}
editor_mode.prototype.tower = function (callback) {
var objs = [];
editor.file.editTower([], function (objs_) {
objs = objs_;
//console.log(objs_)
});
//只查询不修改时,内部实现不是异步的,所以可以这么写
var tableinfo = editor.table.objToTable(objs[0], objs[1]);
document.getElementById('table_b6a03e4c_5968_4633_ac40_0dfdd2c9cde5').innerHTML = tableinfo.HTML;
tableinfo.listen(tableinfo.guids);
if (Boolean(callback)) callback();
}
editor_mode.prototype.functions = function (callback) {
var objs = [];
editor.file.editFunctions([], function (objs_) {
objs = objs_;
//console.log(objs_)
});
//只查询不修改时,内部实现不是异步的,所以可以这么写
var tableinfo = editor.table.objToTable(objs[0], objs[1]);
document.getElementById('table_e260a2be_5690_476a_b04e_dacddede78b3').innerHTML = tableinfo.HTML;
tableinfo.listen(tableinfo.guids);
if (Boolean(callback)) callback();
}
editor_mode.prototype.commonevent = function (callback) {
var objs = [];
editor.file.editCommonEvent([], function (objs_) {
objs = objs_;
//console.log(objs_)
});
//只查询不修改时,内部实现不是异步的,所以可以这么写
var tableinfo = editor.table.objToTable(objs[0], objs[1]);
document.getElementById('table_b7bf0124_99fd_4af8_ae2f_0017f04a7c7d').innerHTML = tableinfo.HTML;
tableinfo.listen(tableinfo.guids);
if (Boolean(callback)) callback();
}
editor_mode.prototype.plugins = function (callback) {
var objs = [];
editor.file.editPlugins([], function (objs_) {
objs = objs_;
//console.log(objs_)
});
//只查询不修改时,内部实现不是异步的,所以可以这么写
var tableinfo = editor.table.objToTable(objs[0], objs[1]);
document.getElementById('table_e2c034ec_47c6_48ae_8db8_4f8f32fea2d6').innerHTML = tableinfo.HTML;
tableinfo.listen(tableinfo.guids);
if (Boolean(callback)) callback();
}
/////////////////////////////////////////////////////////////////////////////
/**
* editor.dom.editModeSelect.onchange
*/
editor_mode.prototype.editModeSelect_onchange = function () {
editor_mode.change(editor.dom.editModeSelect.value);
}
editor_mode.prototype.listen = function (callback) {
// 移动至 editor_listen.js -> editor.constructor.prototype.mode_listen
}
var editor_mode = new editor_mode();
editor_mode.init_dom_ids();
return editor_mode;
}
//editor_mode = editor_mode(editor);

491
_server/editor_multi.js Normal file
View File

@ -0,0 +1,491 @@
editor_multi = function () {
var editor_multi = {};
var extraKeys = {
"Ctrl-/": function (cm) { cm.toggleComment(); },
"Ctrl-B": function (cm) { ternServer.jumpToDef(cm); },
"Ctrl-Q": function(cm) { ternServer.rename(cm); },
"Cmd-F": CodeMirror.commands.findPersistent,
"Ctrl-F": CodeMirror.commands.findPersistent,
"Ctrl-R": CodeMirror.commands.replaceAll,
"Ctrl-D": function(cm){ cm.foldCode(cm.getCursor()); },
"Ctrl-O": function () { editor_multi.openUrl('/_docs/#/api'); },
"Ctrl-P": function () { editor_multi.openUrl('https://h5mota.com/plugins/'); }
};
var codeEditor = CodeMirror.fromTextArea(document.getElementById("multiLineCode"), {
lineNumbers: true,
matchBrackets: true,
indentUnit: 4,
tabSize: 4,
indentWithTabs: true,
smartIndent: true,
mode: { name: "javascript", globalVars: true, localVars: true },
lineWrapping: true,
continueComments: "Enter",
gutters: ["CodeMirror-lint-markers", "CodeMirror-linenumbers", "CodeMirror-foldgutter"],
lint: true,
autocomplete: true,
autoCloseBrackets: true,
styleActiveLine: true,
extraKeys: extraKeys,
foldGutter: true,
inputStyle: "textarea",
highlightSelectionMatches: { showToken: /\w/, annotateScrollbar: true }
});
var commandsName = {
'Ctrl-/': '注释当前选中行Ctrl+/',
'Ctrl-B': '跳转到定义Ctrl+B',
'Ctrl-Q': '重命名变量Ctrl+Q',
'Ctrl-F': '查找Ctrl+F',
'Ctrl-R': '全部替换Ctrl+R',
'Ctrl-D': '折叠或展开块Ctrl+D',
'Ctrl-O': '打开API列表Ctrl+O',
'Ctrl-P': '打开在线插件列表Ctrl+P'
};
document.getElementById('codemirrorCommands').innerHTML =
"<option value='' selected>执行操作...</option>" +
Object.keys(commandsName).map(function (name) {
return "<option value='" + name + "'>" + commandsName[name] + "</option>"
}).join('');
var coredef = terndefs_f6783a0a_522d_417e_8407_94c67b692e50[2];
Object.keys(core.material.enemys).forEach(function (name){
coredef.core.material.enemys[name] = {
"!type": "enemy",
"!doc": core.material.enemys[name].name || "怪物"
}
});
Object.keys(core.material.bgms).forEach(function (name) {
coredef.core.material.bgms[name] = {
"!type": "audio",
"!doc": "背景音乐"
}
});
Object.keys(core.material.sounds).forEach(function (name) {
coredef.core.material.sounds[name] = {
"!type": "audio",
"!doc": "音效"
}
});
Object.keys(core.material.animates).forEach(function (name) {
coredef.core.material.animates[name] = {
"!type": "animate",
"!doc": "动画"
}
});
Object.keys(core.material.images).forEach(function (name) {
if (core.material.images[name] instanceof Image) {
coredef.core.material.images[name] = {
"!type": "image",
"!doc": "系统图片"
}
} else {
coredef.core.material.images[name] = {
"!doc": name == 'autotile' ? '自动元件' : name == 'tilesets' ? '额外素材' : name == 'images' ? '自定义图片' : '系统图片'
}
for (var v in core.material.images[name]) {
coredef.core.material.images[name][v] = {
"!type": "image",
}
}
}
})
Object.keys(core.material.items).forEach(function (name) {
coredef.core.material.items[name] = {
"!type": "item",
"!doc": core.material.items[name].name || "道具"
}
});
functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a.enemys.getSpecials().forEach(function (one) {
var name = one[1];
if (name instanceof Function) name = name({});
coredef.core.enemys.hasSpecial["!doc"] += name + "(" + one[0] + "); ";
});
Object.keys(core.canvas).forEach(function (name) {
coredef.core.canvas[name] = {
"!type": "CanvasRenderingContext2D",
"!doc": "系统画布"
}
});
Object.keys(core.status.maps).forEach(function (name) {
coredef.core.status.maps[name] = {
"!type": "floor",
"!doc": core.status.maps[name].title || ''
}
coredef.core.status.bgmaps[name] = {
"!type": "[[number]]",
"!doc": core.status.maps[name].title || ''
}
coredef.core.status.fgmaps[name] = {
"!type": "[[number]]",
"!doc": core.status.maps[name].title || ''
}
});
Object.keys(core.status.shops).forEach(function (id) {
coredef.core.status.shops[id] = {
"!doc": core.status.shops[id].textInList || "全局商店"
}
});
Object.keys(core.status.textAttribute).forEach(function (id) {
coredef.core.status.textAttribute[id] = {};
});
// --- 转发函数
for (var name in coredef.core) {
if (typeof coredef.core[name] === 'object') {
for (var funcname in coredef.core[name]) {
var one = coredef.core[name][funcname] || {};
var type = one["!type"] || "";
if (type.startsWith("fn(")) {
var forwardname = (functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a[name] || {})[funcname] ? '脚本编辑' : name;
coredef.core[funcname] = {
"!type": one["!type"],
"!doc": one["!doc"] + "<br/>(转发到" + forwardname + "中)"
};
if (one["!url"]) coredef.core[funcname]["!url"] = one["!url"];
}
}
for (var funcname in core[name]) {
if (!(core[name][funcname] instanceof Function) || funcname.charAt(0) == '_' || coredef.core[name][funcname]) continue;
var parameterInfo = /^\s*function\s*[\w_$]*\(([\w_,$\s]*)\)\s*\{/.exec(core[name][funcname].toString());
var parameters = (parameterInfo == null ? "" : parameterInfo[1])
.replace(/\s*/g, '').replace(/,/g, ', ').split(', ')
.filter(function (one) { return one.trim() != ''; })
.map(function (one) { return one.trim() + ': ?'; }).join(', ');
coredef.core[funcname] = coredef.core[name][funcname] = {
"!type": "fn(" + parameters + ")"
}
}
}
}
Object.keys(core.values).forEach(function (id) {
var one = data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc._data.values._data[id];
if (!one) return;
coredef.core.values[id] = {
"!type": "number",
"!doc": one._data,
}
});
Object.keys(core.flags).forEach(function (id) {
var one = data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc._data.flags._data[id];
if (!one) return;
coredef.core.flags[id] = {
"!type": id == 'statusBarItems' ? '[string]' : 'bool',
"!doc": one._data,
}
});
var ternServer = new CodeMirror.TernServer({
defs: terndefs_f6783a0a_522d_417e_8407_94c67b692e50,
plugins: {
doc_comment: true,
complete_strings: true,
},
useWorker: false
});
editor_multi.ternServer = ternServer;
editor_multi.codeEditor = codeEditor;
codeEditor.on("cursorActivity", function (cm) {
var cursor = cm.getCursor();
if (codeEditor.getOption("autocomplete") && !(cursor.line == 0 && cursor.ch == 0)) {
ternServer.updateArgHints(cm);
ternServer.showDocs(cm);
}
});
var ctrlRelease = new Date();
codeEditor.on("keyup", function (cm, event) {
var date = new Date();
if (event.keyCode == 17 || event.keyCode == 91) { // ctrl, cmd
ctrlRelease = date;
}
else if (codeEditor.getOption("autocomplete") && !event.ctrlKey && date - ctrlRelease >= 1000 && (
(event.keyCode >= 65 && event.keyCode <= 90) ||
(!event.shiftKey && event.keyCode == 190) || (event.shiftKey && event.keyCode == 189))) {
try {
ternServer.complete(cm);
} catch (e) {
}
}
});
editor_multi.id = '';
editor_multi.isString = false;
editor_multi.lintAutocomplete = false;
var lastOffset = {};
editor_multi.show = function () {
if (typeof (selectBox) !== typeof (undefined)) selectBox.isSelected(false);
var valueNow = codeEditor.getValue();
//try{eval('function _asdygakufyg_() { return '+valueNow+'\n}');editor_multi.lintAutocomplete=true;}catch(ee){}
if (valueNow.slice(0, 8) === 'function') editor_multi.lintAutocomplete = true;
editor_multi.setLint();
document.getElementById('left7').style = '';
}
editor_multi.hide = function () {
document.getElementById('left7').style = 'z-index:-1;opacity: 0;';
}
editor_multi.setLint = function () {
codeEditor.setOption("lint", editor_multi.lintAutocomplete);
codeEditor.setOption("autocomplete", editor_multi.lintAutocomplete);
document.getElementById("lintCheckbox").checked = editor_multi.lintAutocomplete;
}
editor_multi.toggerLint = function () {
editor_multi.lintAutocomplete = document.getElementById("lintCheckbox").checked;
editor_multi.setLint();
}
editor_multi.indent = function (field) {
if (typeof (editor) !== typeof (undefined) && editor && editor.mode && editor.mode.indent) return editor.mode.indent(field);
return '\t';
}
var _format = function () {
if (!editor_multi.lintAutocomplete) return;
var offset = (codeEditor.getScrollInfo() || {}).top || 0;
_setValue(js_beautify(codeEditor.getValue(), {
brace_style: "collapse-preserve-inline",
indent_with_tabs: true,
jslint_happy: true
}));
codeEditor.scrollTo(0, offset);
}
var _setValue = function (val) {
codeEditor.setValue(val || '');
ternServer.delDoc('doc');
ternServer.addDoc('doc', new CodeMirror.Doc(val || '', 'javascript'));
}
editor_multi.format = function () {
if (!editor_multi.lintAutocomplete) {
alert("只有代码才能进行格式化操作!");
return;
}
_format();
}
editor_multi.hasError = function () {
if (!editor_multi.lintAutocomplete) return false;
return JSHINT.errors.filter(function (e) {
return e.code.startsWith("E")
}).length > 0;
}
var _previewButton = document.getElementById('editor_multi_preview');
_previewButton.onclick = function () {
if (!editor_multi.preview) return;
_format();
if (editor_multi.hasError()) {
alert("当前好像存在严重的语法错误,请处理后再预览。");
return;
}
editor.uievent.previewEditorMulti(editor_multi.preview, codeEditor.getValue());
}
editor_multi.import = function (id_, args) {
var thisTr = document.getElementById(id_);
if (!thisTr) return false;
var input = thisTr.children[2].children[0].children[0];
var field = thisTr.children[0].getAttribute('title');
var comment = thisTr.children[1].getAttribute('title');
if (!input.type || input.type !== 'textarea') return false;
editor_multi.id = id_;
editor_multi.isString = false;
editor_multi.lintAutocomplete = false;
editor_multi.preview = args.preview;
_previewButton.style.display = editor_multi.preview ? 'inline' : 'none';
if (args.lint === true) editor_multi.lintAutocomplete = true;
if ((!input.value || input.value == 'null') && args.template)
input.value = '"' + args.template + '"';
if ((!input.value || input.value == 'null') && editor_mode.mode == 'plugins')
input.value = '"function () {\\n\\t// 在此增加新插件\\n\\t\\n}"';
// if ((!input.value || input.value == 'null') && args)
if (input.value.slice(0, 1) === '"' || args.string) {
editor_multi.isString = true;
_setValue(JSON.parse(input.value) || '');
} else {
var num = editor_multi.indent(field);
eval('var tobj=' + (input.value || 'null'));
var tmap = {};
var tstr = JSON.stringify(tobj, function (k, v) {
if (typeof (v) === typeof ('') && v.slice(0, 8) === 'function') {
var id_ = editor.util.guid();
tmap[id_] = v.toString();
return id_;
} else return v
}, num);
for (var id_ in tmap) {
tstr = tstr.replace('"' + id_ + '"', tmap[id_])
}
_setValue(tstr || '');
}
editor_multi.show();
codeEditor.scrollTo(0, lastOffset[editor_multi.id] || 0);
return true;
}
editor_multi.cancel = function () {
if (editor_multi.id && editor_multi.id != 'callFromBlockly' && editor_multi.id != 'importFile') {
lastOffset[editor_multi.id] = (codeEditor.getScrollInfo() || {}).top;
}
editor_multi.hide();
editor_multi.id = '';
multiLineArgs = [null, null, null];
}
editor_multi.confirm = function (keep) {
if (editor_multi.hasError()) {
alert("当前好像存在严重的语法错误,请处理后再保存。\n严重的语法错误可能会导致整个编辑器的崩溃。");
return;
}
if (!editor_multi.id) {
editor_multi.id = '';
return;
}
if (editor_multi.id === 'callFromBlockly') {
// ----- 自动格式化
_format();
editor_multi.multiLineDone(keep);
return;
}
if (editor_multi.id === 'importFile') {
_format();
editor_multi.writeFileDone(keep);
return;
}
var setvalue = function (value) {
var thisTr = document.getElementById(editor_multi.id);
var input = thisTr.children[2].children[0].children[0];
if (editor_multi.isString) {
input.value = JSON.stringify(value);
} else {
eval('var tobj=' + (value || 'null'));
var tmap = {};
var tstr = JSON.stringify(tobj, function (k, v) {
if (v instanceof Function) {
var id_ = editor.util.guid();
tmap[id_] = v.toString();
return id_;
} else return v
}, 4);
for (var id_ in tmap) {
tstr = tstr.replace('"' + id_ + '"', JSON.stringify(tmap[id_]))
}
input.value = tstr;
}
if (!keep) {
editor_multi.id = '';
editor_multi.hide();
} else {
alert('写入成功!');
}
input.onchange();
}
lastOffset[editor_multi.id] = (codeEditor.getScrollInfo() || {}).top;
// ----- 自动格式化
_format();
setvalue(codeEditor.getValue() || '');
}
editor_multi.doCommand = function (select) {
var value = select.value;
select.selectedIndex = 0;
if (extraKeys[value]) {
extraKeys[value](codeEditor);
}
}
editor_multi.openUrl = function (url) {
if (editor.isMobile && !confirm('你确定要离开本页面么?')) return;
window.open(url, '_blank');
}
var multiLineArgs = [null, null, null];
editor_multi.multiLineEdit = function (value, b, f, args, callback) {
editor_multi.id = 'callFromBlockly';
_setValue(value.split('\\n').join('\n') || '');
multiLineArgs[0] = b;
multiLineArgs[1] = f;
multiLineArgs[2] = callback;
editor_multi.lintAutocomplete = Boolean(args.lint);
editor_multi.show();
}
editor_multi.multiLineDone = function (keep) {
if (!multiLineArgs[0] || !multiLineArgs[1] || !multiLineArgs[2]) return;
var newvalue = codeEditor.getValue() || '';
multiLineArgs[2](newvalue, multiLineArgs[0], multiLineArgs[1])
if (!keep) {
editor_multi.id = '';
editor_multi.hide();
} else {
alert('写入成功!');
}
}
var _fileValues = ['']
editor_multi.importFile = function (filename) {
editor_multi.id = 'importFile'
_fileValues[0] = filename
_setValue('loading')
editor_multi.show();
fs.readFile(filename, 'base64', function (e, d) {
if (e) {
_setValue('加载文件失败:\n' + e)
editor_multi.id = ''
return;
}
var str = editor.util.decode64(d)
_setValue(str)
_fileValues[1] = str
})
}
editor_multi.writeFileDone = function (keep) {
fs.writeFile(_fileValues[0], editor.util.encode64(codeEditor.getValue() || ''), 'base64', function (err, data) {
if (err) printe('文件写入失败,请手动粘贴至' + _fileValues[0] + '\n' + err);
else {
if (!keep) {
editor_multi.id = '';
editor_multi.hide();
} else {
alert('写入成功!');
}
printf(_fileValues[0] + " 写入成功F5刷新后生效");
}
});
}
editor_multi.editCommentJs = function (mod) {
var dict = {
loc: '_server/table/comment.js',
enemyitem: '_server/table/comment.js',
floor: '_server/table/comment.js',
tower: '_server/table/data.comment.js',
functions: '_server/table/functions.comment.js',
commonevent: '_server/table/events.comment.js',
plugins: '_server/table/plugins.comment.js',
}
editor_multi.lintAutocomplete = true
editor_multi.setLint()
editor_multi.importFile(dict[mod])
}
return editor_multi;
}
//editor_multi=editor_multi();

602
_server/editor_table.js Normal file
View File

@ -0,0 +1,602 @@
editor_table_wrapper = function (editor) {
editor_table = function () {
}
/////////////////////////////////////////////////////////////////////////////
// HTML模板
editor_table.prototype.select = function (value, values) {
if (values.indexOf(value) < 0) values = [value].concat(values);
var content = values.map(function (v) {
return editor.table.option(v, v == value)
}).join('')
return /* html */`<select>\n${content}</select>\n`
}
editor_table.prototype.option = function (value, selected) {
return /* html */`<option value='${JSON.stringify(value)}' ${selected ? 'selected' : ''}>${JSON.stringify(value)}</option>\n`
}
editor_table.prototype.text = function (value) {
return /* html */`<input type='text' spellcheck='false' value='${JSON.stringify(value)}'/>\n`
}
editor_table.prototype.checkbox = function (value) {
return /* html */`<input type='checkbox' class='checkbox' ${(value ? 'checked ' : '')}/>\n`
}
editor_table.prototype.textarea = function (value, indent, disable) {
return /* html */`<textarea spellcheck='false' ${disable ? 'disabled readonly' : ''}>${JSON.stringify(value, null, indent || 0)}</textarea>\n`
}
editor_table.prototype.checkboxSet = function (value, keys, prefixStrings) {
if (value == null) value = [];
if (!(value instanceof Array)) {
if (value == 0) value = [];
else value = [value];
}
keys=Array.from(keys)
prefixStrings=Array.from(prefixStrings)
for (var index = 0; index < value.length; index++) {
if (keys.indexOf(value[index])==-1) {
keys.push(value[index])
prefixStrings.push('<br>'+value[index]+': ')
}
}
var content=[]
for (var index = 0; index < keys.length; index++) {
content.push(editor.table.checkboxSetMember(value.indexOf(keys[index])!=-1,keys[index],prefixStrings[index]))
}
return /* html */`<div class='checkboxSet'>${content.join('')}</div>\n`;
}
editor_table.prototype.checkboxSetMember = function (value,key,prefixString) {
return /* html */`${prefixString}<input key='${key}' ctype='${typeof key}' type='checkbox' class='checkboxSetMember' onchange='editor.table.checkboxSetMemberOnchange(this)' ${(value ? 'checked ' : '')}/>\n`;
}
editor_table.prototype.editGrid = function (showComment, type) {
var list = [];
if (showComment) list.push("<button onclick='editor.table.onCommentBtnClick(this)'>注释</button>");
if (type != 'select' && type != 'checkbox' && type != 'checkboxSet' && type != 'popCheckboxSet' && type != 'disable')
list.push("<button onclick='editor.table.onEditBtnClick(this)' class='editorTableEditBtn'>编辑</button>");
if (type == 'popCheckboxSet')
list.push("<button onclick='editor.table.onEditBtnClick(this)' class='editorTableEditBtn'>多选框编辑</button>");
if (type == 'disable') list.push("<button onclick='editor.table.onCopyBtnClick(this)'>复制</button>");
return list.join(' ');
}
editor_table.prototype.title = function () {
return /* html */`\n<tr><td>条目</td><td>注释</td><td>值</td><td>操作</td></tr>\n`
}
editor_table.prototype.gap = function (field) {
var tokenlist = field.slice(2, -2).split("']['");
var rule = tokenlist.join("-");
tokenlist.pop();
var self = tokenlist.join("-");
var status = !!tokenPool[rule];
return /* html */`<tr data-gap="${rule}" data-field="${self}">
<td>----</td>
<td>----</td>
<td>${field}</td>
<td><button class='editorTableFoldBtn' onclick='editor.table.onFoldBtnClick(this)' data-fold="${ status ? "true" : "false" }">${ status ? "展开" : "折叠" }</button></td>
</tr>\n`
}
editor_table.prototype.tr = function (guid, field, shortField, commentHTMLescape, cobjstr, shortComment, tdstr, type) {
return /* html */`<tr id="${guid}" data-field="${field.slice(2, -2).split("']['").join("-")}">
<td title="${field}">${shortField}</td>
<td title="${commentHTMLescape}" cobj="${cobjstr}">${shortComment || commentHTMLescape}</td>
<td><div class="etableInputDiv ${type}">${tdstr}</div></td>
<td>${editor.table.editGrid(shortComment, type)}</td>
</tr>\n`
}
/**
* checkboxset中checkbox的onchange
* 这个函数本质是模板editor_table.prototype.checkboxSetMember的一部分
* 故放在HTML模板分类下
*/
editor_table.prototype.checkboxSetMemberOnchange = function (onemember) {
var thisset=onemember.parentNode
var inputs=thisset.children
var value=[]
for (var i in inputs) {
if (inputs[i].nodeName == 'INPUT') {
if (inputs[i].checked) {
var one = inputs[i].getAttribute('key');
if (inputs[i].getAttribute('ctype') == 'number') one = parseFloat(one);
value.push(one);
}
}
}
thiseval = value;
// if (value.length == 0) thiseval = null;
thisset.value=JSON.stringify(thiseval)
thisset.onchange()
}
/////////////////////////////////////////////////////////////////////////////
// 表格生成的控制
/**
* 注释对象的默认值
*/
editor_table.prototype.defaultcobj = {
// 默认是文本域
_type: 'textarea',
_data: '',
_string: function (args) {//object~[field,cfield,vobj,cobj]
var thiseval = args.vobj;
return (typeof (thiseval) === typeof ('')) && thiseval[0] === '"';
},
// 默认情况下 非对象和数组的视为叶节点
_leaf: function (args) {//object~[field,cfield,vobj,cobj]
var thiseval = args.vobj;
if (thiseval == null || thiseval == undefined) return true;//null,undefined
if (typeof (thiseval) === typeof ('')) return true;//字符串
if (Object.keys(thiseval).length === 0) return true;//数字,true,false,空数组,空对象
return false;
},
}
/**
* 把来自数据文件的obj和来自*comment.js的commentObj组装成表格
* commentObj在无视['_data']的意义下与obj同形
* : commentObj['_data']['a']['_data']['b'] obj['a']['b'] 是对应的
* 在此意义下, 两者的结构是一致的
* 在commentObj没有被定义的obj的分支, 会取defaultcobj作为默认值
* 因此在深度优先遍历时,维护
* field="['a']['b']"
* cfield="['_data']['a']['_data']['b']"
* vobj=obj['a']['b']
* cobj=commentObj['_data']['a']['_data']['b']
* cobj
* cobj = Object.assign({}, defaultcobj, pcobj['_data'][ii])
* 每一项若未定义,就从defaultcobj中取
* 当其是函数不是具体值时,把args = {field: field, cfield: cfield, vobj: vobj, cobj: cobj}代入算出该值
* 得到的叶节点的<tr>结构如下
* tr>td[title=field]
* >td[title=comment,cobj=cobj:json]
* >td>div>input[value=thiseval]
* 返回结果
* 返回一个对象, 假设被命名为tableinfo
* 在把一个 table innerHTML 赋值为 tableinfo.HTML
* 再调 tableinfo.listen(tableinfo.guids) 进行绑定事件
* @param {Object} obj
* @param {Object} commentObj
* @returns {{"HTML":String,"guids":String[],"listen":Function}}
*/
editor_table.prototype.objToTable = function (obj, commentObj) {
// 表格抬头
var outstr = [editor.table.title()];
var guids = [];
var defaultcobj = this.defaultcobj
/**
* 深度优先遍历, p*即为父节点的四个属性
* @param {String} pfield
* @param {String} pcfield
* @param {Object} pvobj
* @param {Object} pcobj
*/
var recursionParse = function (pfield, pcfield, pvobj, pcobj) {
var keysForTableOrder = {};
var voidMark = {};
// 1. 按照pcobj排序生成
if (pcobj && pcobj['_data']) {
for (var ii in pcobj['_data']) keysForTableOrder[ii] = voidMark;
}
// 2. 对每个pvobj且不在pcobj的再添加到最后
keysForTableOrder = Object.assign(keysForTableOrder, pvobj)
for (var ii in keysForTableOrder) {
// 3. 对于pcobj有但是pvobj中没有的, 弹出提示, (正常情况下editor_file会补全成null)
// 事实上能执行到这一步工程没崩掉打不开,就继续吧..
if (keysForTableOrder[ii] === voidMark) {
if (typeof id_815975ad_ee6f_4684_aac7_397b7e392702 === "undefined") {
// alert('comment和data不匹配,请在群 HTML5造塔技术交流群 959329661 内反馈')
console.error('comment和data不匹配,请在群 HTML5造塔技术交流群 959329661 内反馈')
id_815975ad_ee6f_4684_aac7_397b7e392702 = 1;
}
pvobj[ii] = null;
}
var field = pfield + "['" + ii + "']";
var cfield = pcfield + "['_data']['" + ii + "']";
var vobj = pvobj[ii];
var cobj = null;
if (pcobj && pcobj['_data'] && pcobj['_data'][ii]) {
// cobj存在时直接取
cobj = Object.assign({}, defaultcobj, pcobj['_data'][ii]);
} else {
// 当其函数时代入参数算出cobj, 不存在时只取defaultcobj
if (pcobj && (pcobj['_data'] instanceof Function)) cobj = Object.assign({}, defaultcobj, pcobj['_data'](ii));
else cobj = Object.assign({}, defaultcobj);
}
var args = { field: field, cfield: cfield, vobj: vobj, cobj: cobj }
// 当cobj的参数为函数时,代入args算出值
for (var key in cobj) {
if (key === '_data') continue;
if (cobj[key] instanceof Function) cobj[key] = cobj[key](args);
}
pvobj[ii] = vobj = args.vobj;
// 标记为_hide的属性不展示
if (cobj._hide) continue;
if (!cobj._leaf) {
// 不是叶节点时, 插入展开的标记并继续遍历, 此处可以改成按钮用来添加新项或折叠等
outstr.push(editor.table.gap(field));
recursionParse(field, cfield, vobj, cobj);
} else {
// 是叶节点时, 调objToTr_渲染<tr>
var leafnode = editor.table.objToTr(obj, commentObj, field, cfield, vobj, cobj);
outstr.push(leafnode[0]);
guids.push(leafnode[1]);
}
}
}
// 开始遍历
recursionParse("", "", obj, commentObj);
var listen = function (guids) {
// 每个叶节点的事件绑定
var tableid = editor.util.guid();
editor.mode.currentTable=tableid;
guids.forEach(function (guid) {
editor.table.guidListen(guid, tableid, obj, commentObj)
});
}
return { "HTML": outstr.join(''), "guids": guids, "listen": listen };
}
/**
* 返回叶节点<tr>形如
* tr>td[title=field]
* >td[title=comment,cobj=cobj:json]
* >td>div>input[value=thiseval]
* 参数意义在 objToTable 中已解释
* @param {Object} obj
* @param {Object} commentObj
* @param {String} field
* @param {String} cfield
* @param {Object} vobj
* @param {Object} cobj
*/
editor_table.prototype.objToTr = function (obj, commentObj, field, cfield, vobj, cobj) {
var guid = editor.util.guid();
var thiseval = vobj;
var comment = String(cobj._data);
// var charlength = 15;
// "['a']['b']" => "b"
var shortField = field.split("']").slice(-2)[0].split("['").slice(-1)[0];
// 把长度超过 charlength 的字符改成 固定长度+...的形式
// shortField = (shortField.length < charlength ? shortField : shortField.slice(0, charlength) + '...');
// 完整的内容转义后供悬停查看
var commentHTMLescape = editor.util.HTMLescape(comment);
// 把长度超过 charlength 的字符改成 固定长度+...的形式
// var shortCommentHTMLescape = (comment.length < charlength ? commentHTMLescape : editor.util.HTMLescape(comment.slice(0, charlength)) + '...');
var cobjstr = Object.assign({}, cobj);
delete cobjstr._data;
// 把cobj塞到第二个td的[cobj]中, 方便绑定事件时取
cobjstr = editor.util.HTMLescape(JSON.stringify(cobjstr));
var tdstr = editor.table.objToTd(obj, commentObj, field, cfield, vobj, cobj)
var outstr = editor.table.tr(guid, field, shortField, commentHTMLescape, cobjstr, cobj._docs, tdstr, cobj._type)
return [outstr, guid];
}
editor_table.prototype.objToTd = function (obj, commentObj, field, cfield, vobj, cobj) {
var thiseval = vobj;
switch (cobj._type) {
case 'select':
return editor.table.select(thiseval, cobj._select.values);
case 'checkbox':
return editor.table.checkbox(thiseval);
case 'checkboxSet':
return editor.table.checkboxSet(thiseval, cobj._checkboxSet.key, cobj._checkboxSet.prefix);
default:
return editor.table.textarea(thiseval, cobj.indent || 0, cobj._type == 'disable');
}
}
/////////////////////////////////////////////////////////////////////////////
// 表格的用户交互
/**
* 检查一个值是否允许被设置为当前输入
* @param {Object} cobj
* @param {*} thiseval
*/
editor_table.prototype.checkRange = function (cobj, thiseval) {
if (cobj._range) {
return eval(cobj._range);
}
if (cobj._select) {
return cobj._select.values.indexOf(thiseval) !== -1;
}
if (cobj._bool) {
return [true, false].indexOf(thiseval) !== -1;
}
return true;
}
/**
* 监听一个guid对应的表格项
* @param {String} guid
*/
editor_table.prototype.guidListen = function (guid, tableid, obj, commentObj) {
// tr>td[title=field]
// >td[title=comment,cobj=cobj:json]
// >td>div>input[value=thiseval]
var thisTr = document.getElementById(guid);
var input = thisTr.children[2].children[0].children[0];
var field = thisTr.children[0].getAttribute('title');
var cobj = JSON.parse(thisTr.children[1].getAttribute('cobj'));
var modeNode = thisTr.parentNode;
thisTr.setAttribute('tableid',tableid)
while (!editor_mode._ids.hasOwnProperty(modeNode.getAttribute('id'))) {
modeNode = modeNode.parentNode;
}
input.onchange = function () {
editor.table.onchange(guid, obj, commentObj, thisTr, input, field, cobj, modeNode)
}
// 用检测两次单击的方式来实现双击(以支持手机端的双击)
var doubleClickCheck = [0];
thisTr.onclick = function () {
var newClick = new Date().getTime();
var lastClick = doubleClickCheck.shift();
doubleClickCheck.push(newClick);
if (newClick - lastClick < 500) {
editor.table.dblclickfunc(guid, obj, commentObj, thisTr, input, field, cobj, modeNode)
}
}
}
/**
* 表格的值变化时
*/
editor_table.prototype.onchange = function (guid, obj, commentObj, thisTr, input, field, cobj, modeNode) {
editor_mode.onmode(editor_mode._ids[modeNode.getAttribute('id')]);
if (editor.mode.currentTable!=thisTr.getAttribute('tableid')) return;
var thiseval = null;
if (input.checked != null) input.value = input.checked;
try {
if (input.value == '') input.value = 'null';
thiseval = JSON.parse(input.value);
} catch (ee) {
printe(field + ' : ' + ee);
throw ee;
}
if (editor.table.checkRange(cobj, thiseval)) {
editor_mode.addAction(['change', field, thiseval]);
editor_mode.onmode('save');//自动保存 删掉此行的话点保存按钮才会保存
} else {
printe(field + ' : 输入的值不合要求,请鼠标放置在注释上查看说明');
}
}
var tokenPool = {};
var tokenstyle = document.createElement("style");
document.body.appendChild(tokenstyle);
var tokenPoolRender = function() {
var content = "";
Object.keys(tokenPool).forEach(function(k) {
content += /* CSS */`[data-field|=${k}]{ display: none }`;
})
tokenstyle.innerHTML = content;
}
/**
* "折叠"被按下时
*/
editor_table.prototype.onFoldBtnClick = function (button) {
var tr = button.parentNode.parentNode;
if (button.dataset.fold == "true") {
delete tokenPool[tr.dataset.gap];
tokenPoolRender();
button.dataset.fold = "false";
button.innerText = "折叠";
} else {
tokenPool[tr.dataset.gap] = true;
tokenPoolRender();
button.dataset.fold = "true";
button.innerText = "展开";
}
}
/**
* "显示完整注释"被按下时
*/
editor_table.prototype.onCommentBtnClick = function (button) {
var tr = button.parentNode.parentNode;
printf(tr.children[1].getAttribute('title'));
}
/**
* "编辑表格内容"被按下时
*/
editor_table.prototype.onEditBtnClick = function (button) {
var tr = button.parentNode.parentNode;
var guid = tr.getAttribute('id');
var cobj = JSON.parse(tr.children[1].getAttribute('cobj'));
var input = tr.children[2].children[0].children[0];
if (cobj._type === 'event') editor_blockly.import(guid, { type: cobj._event });
if (cobj._type === 'textarea') editor_multi.import(guid, { lint: cobj._lint, string: cobj._string, template: cobj._template, preview: cobj._preview });
if (cobj._type === 'material') editor.table.selectMaterial(input, cobj);
if (cobj._type === 'color') editor.table.selectColor(input);
if (cobj._type === 'point') editor.table.selectPoint(input);
if (cobj._type === 'popCheckboxSet') editor.table.popCheckboxSet(input, cobj);
}
editor_table.prototype.onCopyBtnClick = function (button) {
var tr = button.parentNode.parentNode;
var input = tr.children[2].children[0].children[0];
var value = JSON.parse(input.value);
if (value == null) {
printe('没有赋值的内容');
return;
}
if (core.copy(value.toString())) {
printf('复制成功!');
} else {
printe('无法复制此内容,请手动选择复制');
}
}
/**
* 双击表格时
* 正常编辑: 尝试用事件编辑器或多行文本编辑器打开
* 添加: 在该项的同一级创建一个内容为null新的项, 刷新后生效并可以继续编辑
* 删除: 删除该项, 刷新后生效
* 在点击按钮 添加/删除 ,下一次双击将被视为 添加/删除
*/
editor_table.prototype.dblclickfunc = function (guid, obj, commentObj, thisTr, input, field, cobj, modeNode) {
if (editor_mode.doubleClickMode === 'change') {
if (cobj._type === 'event') editor_blockly.import(guid, { type: cobj._event });
if (cobj._type === 'textarea') editor_multi.import(guid, { lint: cobj._lint, string: cobj._string, template: cobj._template, preview: cobj._preview });
if (cobj._type === 'material') editor.table.selectMaterial(input, cobj);
if (cobj._type === 'color') editor.table.selectColor(input);
if (cobj._type === 'point') editor.table.selectPoint(input);
if (cobj._type === 'popCheckboxSet') editor.table.popCheckboxSet(input, cobj);
} else if (editor_mode.doubleClickMode === 'add') {
editor_mode.doubleClickMode = 'change';
editor.table.addfunc(guid, obj, commentObj, thisTr, input, field, cobj, modeNode)
} else if (editor_mode.doubleClickMode === 'delete') {
editor_mode.doubleClickMode = 'change';
editor.table.deletefunc(guid, obj, commentObj, thisTr, input, field, cobj, modeNode)
}
}
editor_table.prototype.selectMaterial = function (input, cobj) {
editor.uievent.selectMaterial(input.value, cobj._docs || cobj._data || '请选择素材', cobj._directory, function (one) {
if (!/^[-A-Za-z0-9_.]+$/.test(one)) return null;
if (cobj._transform) return eval("("+cobj._transform+")(one)");
return one;
}, function (data) {
input.value = JSON.stringify(cobj._onconfirm ? eval("("+cobj._onconfirm+")(JSON.parse(input.value), data)") : data);
input.onchange();
})
}
editor_table.prototype.selectColor = function (input) {
if (input.value != null) {
var str = input.value.toString().replace(/[^\d.,]/g, '');
if (/^[0-9 ]+,[0-9 ]+,[0-9 ]+(,[0-9. ]+)?$/.test(str)) {
document.getElementById('colorPicker').value = str;
}
}
var boundingBox = input.getBoundingClientRect();
openColorPicker(boundingBox.x, boundingBox.y + boundingBox.height, function (value) {
value = value.replace(/[^\d.,]/g, '');
input.value = '[' + value +']';
input.onchange();
})
}
editor_table.prototype.selectPoint = function (input) {
var x = 0, y = 0, value = input.value;
if (value != null) {
try {
var loc = JSON.parse(value);
if (loc instanceof Array && loc.length == 2) {
x = loc[0];
y = loc[1];
}
} catch (e) {}
}
editor.uievent.selectPoint(editor.currentFloorId, x, y, false, function (floorId, x, y) {
input.value = '['+x+','+y+']';
input.onchange();
})
}
editor_table.prototype.popCheckboxSet = function (input, cobj) {
editor.uievent.popCheckboxSet(JSON.parse(input.value), cobj._checkboxSet, cobj._docs || cobj._data || '请选择多选项', function (value) {
input.value = JSON.stringify(value);
input.onchange();
})
}
/**
* 删除表格项
*/
editor_table.prototype.deletefunc = function (guid, obj, commentObj, thisTr, input, field, cobj, modeNode) {
editor_mode.onmode(editor_mode._ids[modeNode.getAttribute('id')]);
if (editor.table.checkRange(cobj, null)) {
editor_mode.addAction(['delete', field, undefined]);
editor_mode.onmode('save', function () {
printf('删除成功,刷新后生效。')
});
} else {
printe(field + ' : 该值不允许为null无法删除');
}
}
/**
* 添加表格项
*/
editor_table.prototype.addfunc = function (guid, obj, commentObj, thisTr, input, field, cobj, modeNode) {
if (modeNode) {
editor_mode.onmode(editor_mode._ids[modeNode.getAttribute('id')]);
}
var mode = editor.dom.editModeSelect.value;
var supportText = mode === 'commonevent' || mode === 'plugins';
if (obj == null) {
if (mode === 'commonevent') obj = events_c12a15a8_c380_4b28_8144_256cba95f760;
else if (mode === 'plugins') obj = plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1;
else return;
}
// 1.输入id
var newid = '2';
if (mode == 'loc') {
var ae = editor.currentFloorData.autoEvent[editor_mode.pos.x + ',' + editor_mode.pos.y];
if (ae != null) {
var testid;
for (testid = 2; Object.hasOwnProperty.call(ae, testid); testid++); // 从3开始是因为comment中设置了始终显示012
newid = testid + '';
}
} else {
newid = prompt(supportText ? '请输入新项的ID支持中文' : '请输入新项的ID数字字母下划线');
if (newid == null || newid.length == 0) {
return;
}
}
// 2.检查id是否符合规范或与已有id重复
if (!supportText) {
if (!/^[a-zA-Z0-9_]+$/.test(newid)) {
printe('id不符合规范, 请使用大小写字母数字下划线来构成');
return;
}
}
var conflict = true;
var basefield = (field || "").replace(/\[[^\[]*\]$/, '');
if (basefield === "['main']") {
printe("全塔属性 ~ ['main'] 不允许添加新值");
return;
}
try {
var baseobj = eval('obj' + basefield);
conflict = newid in baseobj;
} catch (ee) {
// 理论上这里不会发生错误
printe(ee);
throw ee;
}
if (conflict) {
printe('id已存在, 请直接修改该项的值');
return;
}
// 3.添加
editor_mode.addAction(['add', basefield + "['" + newid + "']", null]);
editor_mode.onmode('save', function () {
printf('添加成功,刷新后生效;也可以继续新增其他项目。')
});//自动保存 删掉此行的话点保存按钮才会保存
}
/////////////////////////////////////////////////////////////////////////////
editor.constructor.prototype.table = new editor_table();
}
//editor_table_wrapper(editor);

339
_server/editor_ui.js Normal file
View File

@ -0,0 +1,339 @@
editor_ui_wrapper = function (editor) {
var tip=document.getElementById('tip');
var print = function (msg, cls) {
if (msg == '') {
tip.innerHTML = '';
return;
}
tip.innerHTML = '<p class="'+cls+'">' + msg + "</p>";
}
window.printf = function (msg) {
selectBox.isSelected(false);
print(msg, 'successText');
}
window.printe = function (msg) {
selectBox.isSelected(false);
print(msg, 'warnText');
}
window.printi = function (msg) {
print(msg, 'infoText');
}
editor.uifunctions.showBlockInfo = function (value) {
if (value == 0) {
printi("当前选择为清除块,可擦除地图上块");
return;
}
var hasId = 'id' in value;
if (hasId && value.idnum == 17) {
printi("当前选择为空气墙, 在编辑器中可视, 在游戏中隐藏的墙, 用来配合前景/背景的贴图");
return;
}
var isAutotile = hasId && value.images == "autotile";
tip.innerHTML = (hasId?`<p>图块编号:<span class="infoText">${ value['idnum'] }</span></p>
<p>图块ID<span class="infoText">${ value['id'] }</span></p>`:`
<p class="warnText">该图块无对应的数字或ID存在请先前往icons.js和maps.js中进行定义</p>`)+`
<p>图块所在素材<span class="infoText">${ value['images'] + (isAutotile ? '( '+value['id']+' )' : '') }</span>
</p>
<p>图块索引<span class="infoText">${ value['y'] }</span></p>`;
}
editor.uifunctions.showTips = function (value) {
var tips = [
'表格的文本域可以双击进行编辑',
'双击地图可以选中素材,右键可以弹出菜单',
'双击事件编辑器的图块可以进行长文本编辑/脚本编辑/地图选点/UI绘制预览等操作',
'ESC或点击空白处可以自动保存当前修改',
'H键可以打开操作帮助哦',
'tileset平铺模式可以在地图上拖动来平铺框选的图形',
'可以拖动地图上的图块和事件或按Ctrl+C, Ctrl+X和Ctrl+V进行复制剪切和粘贴Delete删除右键也可以拉框选择区域',
'Alt+数字键保存图块,数字键读取保存的图块',
];
if (value == null) value = Math.floor(Math.random() * tips.length);
printf('tips: ' + tips[value])
}
/**
* 根据鼠标点击, 得到从元素向上到body的所有id
*/
editor.uifunctions.getClickpath = function (e) {
//console.log(e);
var clickpath = [];
var getpath = function (e) {
var path = [];
var currentElem = e.target;
while (currentElem) {
path.push(currentElem);
currentElem = currentElem.parentElement;
}
if (path.indexOf(window) === -1 && path.indexOf(document) === -1)
path.push(document);
if (path.indexOf(window) === -1)
path.push(window);
return path;
}
getpath(e).forEach(function (node) {
if (!node.getAttribute) return;
var id_ = node.getAttribute('id');
if (id_) {
if (['left', 'left1', 'left2', 'left3', 'left4', 'left5', 'left8', 'mobileview'].indexOf(id_) !== -1) clickpath.push('edit');
clickpath.push(id_);
}
});
return clickpath;
}
/**
* editor.dom.body.onmousedown
* 检测鼠标点击,
* + 如果选中了绘图区域之外, 就保存地图
* + 维护绘图区的菜单的隐藏
* + 记录最后一次点击的id(主要为了数据区服务)
*/
editor.uifunctions.body_click = function (e) {
var clickpath = editor.uifunctions.getClickpath(e);
var unselect = true;
for (var ii = 0, thisId; thisId = ['edit', 'tip', 'brushMod', 'brushMod2', 'brushMod3', 'brushMode4', 'layerMod', 'layerMod2', 'layerMod3', 'viewportButtons'][ii]; ii++) {
if (clickpath.indexOf(thisId) !== -1) {
unselect = false;
break;
}
}
if (unselect && !editor.uivalues.lockMode) {
if (clickpath.indexOf('eui') === -1 && clickpath.indexOf('lastUsed') === -1) {
if (selectBox.isSelected()) {
editor_mode.onmode('');
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw (err)
}
; printf('地图保存成功');
editor.uifunctions.unhighlightSaveFloorButton();
});
}
selectBox.isSelected(false);
editor.info = {};
}
}
//editor.mode.onmode('');
if (e.button != 2 && !editor.isMobile && clickpath.indexOf('midMenu') === -1) {
editor.uifunctions.hideMidMenu();
}
if (clickpath.indexOf('down') !== -1 && clickpath.indexOf('midMenu') === -1 && editor.isMobile) {
editor.uifunctions.hideMidMenu();
}
if (clickpath.length >= 2 && clickpath[0].indexOf('id_') === 0) { editor.lastClickId = clickpath[0] }
}
/**
* editor.dom.body.onkeydown
* 绑定快捷键
*/
editor.uifunctions.body_shortcut = function (e) {
editor.uivalues.tileSize = [1,1];
// UI预览 & 地图选点
if (editor.uievent && editor.uievent.isOpen) {
editor.uievent.onKeyDown(e);
return;
}
// 监听Ctrl+S保存
if (e.ctrlKey && e.keyCode == 83) {
e.preventDefault();
if (editor_multi.id != "") {
editor_multi.confirm(); // 保存脚本编辑器
}
else if (editor_blockly.id != "") {
editor_blockly.confirm(); // 保存事件编辑器
}
else {
editor_mode.saveFloor();
}
return;
}
// 如果是开启事件/脚本编辑器状态,则忽略
if (editor_multi.id != "" || editor_blockly.id != "")
return;
// PGUP和PGDOWN切换楼层
if (e.keyCode == 33 || e.keyCode == 34) {
e.preventDefault();
var saveFloor = document.getElementById('saveFloor');
if (saveFloor && saveFloor.classList.contains('highlight')) {
return;
}
var index = editor.core.floorIds.indexOf(editor.currentFloorId);
var nextIndex = index + (e.keyCode == 33 ? 1 : -1);
if (nextIndex >= 0 && nextIndex < editor.core.floorIds.length) {
var toId = editor.core.floorIds[nextIndex];
editor_mode.onmode('nextChange');
editor_mode.onmode('floor');
document.getElementById('selectFloor').value = toId;
editor.uivalues.recentFloors.push(editor.currentFloorId);
editor.changeFloor(toId);
}
return;
}
var focusElement = document.activeElement;
if (!focusElement || focusElement.tagName.toLowerCase() == 'body'
|| focusElement.id == 'selectFloor' || focusElement.id == 'bigmapBtn'
|| focusElement.id.startsWith('layerMod')) {
//Ctrl+z 撤销上一步undo
if (e.keyCode == 90 && e.ctrlKey) {
e.preventDefault();
if (editor.uivalues.preMapData.length > 0) {
var data = editor.uivalues.preMapData.pop();
editor.dom.maps.forEach(function (one) {
editor[one] = JSON.parse(JSON.stringify(data[one]));
});
editor.updateMap();
editor.uivalues.postMapData.push(data);
editor.uifunctions.highlightSaveFloorButton();
printf("已撤销此操作,你可能需要重新保存地图。");
}
return;
}
//Ctrl+y 重做一步redo
if (e.keyCode == 89 && e.ctrlKey) {
e.preventDefault();
if (editor.uivalues.postMapData.length > 0) {
var data = editor.uivalues.postMapData.pop();
editor.dom.maps.forEach(function (one) {
editor[one] = JSON.parse(JSON.stringify(data[one]));
});
editor.updateMap();
editor.uivalues.preMapData.push(data);
editor.uifunctions.highlightSaveFloorButton();
printf("已重做此操作,你可能需要重新保存地图。");
}
return;
}
// Ctrl+C, Ctrl+X, Ctrl+V
if (e.ctrlKey && e.keyCode == 67 && !selectBox.isSelected()) {
e.preventDefault();
editor.uivalues.copyedInfo = editor.copyFromPos(editor.uivalues.selectedArea);
printf('该点事件已复制;请注意右键地图拉框可以复制一个区域;若有时复制失灵请多点几下空白处');
return;
}
if (e.ctrlKey && e.keyCode == 88 && !selectBox.isSelected()) {
e.preventDefault();
editor.savePreMap();
editor.uivalues.copyedInfo = editor.copyFromPos(editor.uivalues.selectedArea);
editor.clearPos(true, editor.uivalues.selectedArea, function () {
printf('该点事件已剪切;请注意右键地图拉框可以剪切一个区域;若有时剪切失灵请多点几下空白处');
editor.uifunctions.unhighlightSaveFloorButton();
})
return;
}
if (e.ctrlKey && e.keyCode == 86 && !selectBox.isSelected()) {
e.preventDefault();
if (!editor.uivalues.copyedInfo) {
printe("没有复制的事件");
return;
}
editor.savePreMap();
editor.pasteToPos(editor.uivalues.copyedInfo);
editor.updateMap();
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw (err)
}
; printf('粘贴事件成功;若有时粘贴失灵请多点几下空白处');
editor.uifunctions.unhighlightSaveFloorButton();
editor.drawPosSelection();
});
return;
}
// DELETE
if (e.keyCode == 46 && !selectBox.isSelected()) {
editor.savePreMap();
editor.clearPos(true, editor.uivalues.selectedArea, function () {
printf('该点事件已删除;请注意右键地图拉框可以删除一个区域;;若有时删除失灵请多点几下空白处');
editor.uifunctions.unhighlightSaveFloorButton();
})
return;
}
// ESC
if (e.keyCode == 27) {
if (selectBox.isSelected()) {
editor_mode.onmode('');
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw (err)
}
; printf('地图保存成功');
});
}
selectBox.isSelected(false);
editor.info = {};
return;
}
//alt + 0~9 改变快捷图块
if (e.altKey && [48, 49, 50, 51, 52, 53, 54, 55, 56, 57].indexOf(e.keyCode) !== -1) {
var infoToSave = JSON.stringify(editor.info || 0);
if (infoToSave == JSON.stringify({})) return;
editor.uivalues.shortcut[e.keyCode] = JSON.parse(infoToSave);
printf('已保存该快捷图块, 数字键 ' + (e.keyCode - 48) + ' 使用.')
editor.config.set('shortcut', editor.uivalues.shortcut);
return;
}
//ctrl + 0~9 切换到快捷图块
if ([48, 49, 50, 51, 52, 53, 54, 55, 56, 57].indexOf(e.keyCode) !== -1) {
editor.setSelectBoxFromInfo(JSON.parse(JSON.stringify(editor.uivalues.shortcut[e.keyCode] || 0)));
return;
}
switch (e.keyCode) {
// WASD
case 87: editor.moveViewport(0, -1); break;
case 65: editor.moveViewport(-1, 0); break;
case 83: editor.moveViewport(0, 1); break;
case 68: editor.moveViewport(1, 0); break;
// F
case 70: editor.uifunctions.triggerBigmap(); break;
// Z~.
case 90: editor_mode.change('map'); break; // Z
case 88: editor_mode.change('loc'); break; // X
case 67: editor_mode.change('enemyitem'); break; // C
case 86: editor_mode.change('floor'); break; // V
case 66: editor_mode.change('tower'); break; // B
case 78: editor_mode.change('functions'); break; // N
case 77: editor_mode.change('appendpic'); break; // M
case 188: editor_mode.change('commonevent'); break; // ,
case 190: editor_mode.change('plugins'); break; // .
// H
case 72: editor.uifunctions.showHelp(); break;
}
return;
}
}
editor.uifunctions.showHelp = function () {
alert(
"快捷操作帮助:\n" +
"ESC / 点击空白处:自动保存当前修改\n" +
"F切换大地图\n" +
"WASD / 长按箭头:平移大地图\n" +
"PgUp, PgDn / 鼠标滚轮:上下切换楼层\n" +
"Z~.(键盘的第三排):快捷切换标签\n" +
"双击地图:选中对应点的素材\n" +
"右键地图:弹出菜单栏\n" +
"Alt+0~9保存当前使用的图块\n" +
"0~9选中保存的图块\n" +
"Ctrl+Z / Ctrl+Y撤销/重做上次绘制\n" +
"Ctrl+S事件与脚本编辑器的保存并退出\n" +
"双击事件编辑器:长文本编辑/脚本编辑/地图选点/UI绘制预览"
);
}
}

1068
_server/editor_uievent.js Normal file

File diff suppressed because it is too large Load Diff

173
_server/editor_util.js Normal file
View File

@ -0,0 +1,173 @@
editor_util_wrapper = function (editor) {
editor_util = function () {
}
editor_util.prototype.guid = function () {
return 'id_' + 'xxxxxxxx_xxxx_4xxx_yxxx_xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
editor_util.prototype.HTMLescape = function (str_) {
return String(str_).split('').map(function (v) {
return '&#' + v.charCodeAt(0) + ';'
}).join('');
}
editor_util.prototype.getPixel = function (imgData, x, y) {
var offset = (x + y * imgData.width) * 4;
var r = imgData.data[offset + 0];
var g = imgData.data[offset + 1];
var b = imgData.data[offset + 2];
var a = imgData.data[offset + 3];
return [r, g, b, a];
}
editor_util.prototype.setPixel = function (imgData, x, y, rgba) {
var offset = (x + y * imgData.width) * 4;
imgData.data[offset + 0] = rgba[0];
imgData.data[offset + 1] = rgba[1];
imgData.data[offset + 2] = rgba[2];
imgData.data[offset + 3] = rgba[3];
}
// rgbToHsl hue2rgb hslToRgb from https://github.com/carloscabo/colz.git
//--------------------------------------------
// The MIT License (MIT)
//
// Copyright (c) 2014 Carlos Cabo
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//--------------------------------------------
// https://github.com/carloscabo/colz/blob/master/public/js/colz.class.js
var round = Math.round;
var rgbToHsl = function (rgba) {
var arg, r, g, b, h, s, l, d, max, min;
arg = rgba;
if (typeof arg[0] === 'number') {
r = arg[0];
g = arg[1];
b = arg[2];
} else {
r = arg[0][0];
g = arg[0][1];
b = arg[0][2];
}
r /= 255;
g /= 255;
b /= 255;
max = Math.max(r, g, b);
min = Math.min(r, g, b);
l = (max + min) / 2;
if (max === min) {
h = s = 0; // achromatic
} else {
d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
//CARLOS
h = round(h * 360);
s = round(s * 100);
l = round(l * 100);
return [h, s, l];
}
//
var hue2rgb = function (p, q, t) {
if (t < 0) { t += 1; }
if (t > 1) { t -= 1; }
if (t < 1 / 6) { return p + (q - p) * 6 * t; }
if (t < 1 / 2) { return q; }
if (t < 2 / 3) { return p + (q - p) * (2 / 3 - t) * 6; }
return p;
}
var hslToRgb = function (hsl) {
var arg, r, g, b, h, s, l, q, p;
arg = hsl;
if (typeof arg[0] === 'number') {
h = arg[0] / 360;
s = arg[1] / 100;
l = arg[2] / 100;
} else {
h = arg[0][0] / 360;
s = arg[0][1] / 100;
l = arg[0][2] / 100;
}
if (s === 0) {
r = g = b = l; // achromatic
} else {
q = l < 0.5 ? l * (1 + s) : l + s - l * s;
p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
return [round(r * 255), round(g * 255), round(b * 255)];
}
editor_util.prototype.rgbToHsl = rgbToHsl
editor_util.prototype.hue2rgb = hue2rgb
editor_util.prototype.hslToRgb = hslToRgb
editor_util.prototype.encode64 = function (str) {
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
return String.fromCharCode(parseInt(p1, 16))
}))
}
editor_util.prototype.decode64 = function (str) {
return decodeURIComponent(atob(str.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, '')).split('').map(function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
}).join(''))
}
editor_util.prototype.isset = function (val) {
return val != null && !(typeof val == 'number' && isNaN(val));
}
editor_util.prototype.checkCallback = function (callback) {
if (!editor.util.isset(callback)) {
editor.printe('未设置callback');
throw ('未设置callback')
}
}
editor.constructor.prototype.util = new editor_util();
}
//editor_util_wrapper(editor);

186
_server/fs.js Normal file
View File

@ -0,0 +1,186 @@
(function () {
window.fs = {};
var _isset = function (val) {
if (val == undefined || val == null || (typeof val == 'number' && isNaN(val))) {
return false;
}
return true
}
var _http = function (type, url, formData, success, error, mimeType, responseType) {
var xhr = new XMLHttpRequest();
xhr.open(type, url, true);
if (_isset(mimeType))
xhr.overrideMimeType(mimeType);
if (_isset(responseType))
xhr.responseType = responseType;
xhr.onload = function (e) {
if (xhr.status == 200) {
if (_isset(success)) {
success(xhr.response);
}
}
else {
if (_isset(error))
error("HTTP " + xhr.status);
}
};
xhr.onabort = function () {
if (_isset(error))
error("Abort");
}
xhr.ontimeout = function () {
if (_isset(error))
error("Timeout");
}
xhr.onerror = function () {
if (_isset(error))
error("Error on Connection");
}
if (_isset(formData))
xhr.send(formData);
else xhr.send();
}
var postsomething = function (data, _ip, callback) {
if (typeof (data) == typeof ([][0]) || data == null) data = JSON.stringify({ 1: 2 });
_http("POST", _ip, data, function (data) {
if (data.slice(0, 6) == 'error:') {
callback(data, null);
}
else {
callback(null, data);
}
}, function (e) {
if (window.main != null) console.log(e);
else console.log(e);
callback(e + ":请检查启动服务是否处于正常运行状态。");
}, "text/plain; charset=x-user-defined");
}
fs.readFile = function (filename, encoding, callback) {
if (typeof (filename) != typeof (''))
throw 'Type Error in fs.readFile';
if (encoding == 'utf-8') {
//读文本文件
//filename:支持"/"做分隔符
//callback:function(err, data)
//data:字符串
var data = '';
data += 'type=utf8&';
data += 'name=' + filename;
postsomething(data, '/readFile', callback);
return;
}
if (encoding == 'base64') {
//读二进制文件
//filename:支持"/"做分隔符
//callback:function(err, data)
//data:base64字符串
var data = '';
data += 'type=base64&';
data += 'name=' + filename;
postsomething(data, '/readFile', callback);
return;
}
throw 'Type Error in fs.readFile';
}
fs.writeFile = function (filename, datastr, encoding, callback) {
if (typeof (filename) != typeof ('') || typeof (datastr) != typeof (''))
throw 'Type Error in fs.writeFile';
if (encoding == 'utf-8') {
//写文本文件
//filename:支持"/"做分隔符
//callback:function(err)
//datastr:字符串
var data = '';
data += 'type=utf8&';
data += 'name=' + filename;
data += '&value=' + datastr;
postsomething(data, '/writeFile', callback);
return;
}
if (encoding == 'base64') {
//写二进制文件
//filename:支持"/"做分隔符
//callback:function(err)
//datastr:base64字符串
var data = '';
data += 'type=base64&';
data += 'name=' + filename;
data += '&value=' + datastr;
postsomething(data, '/writeFile', callback);
return;
}
throw 'Type Error in fs.writeFile';
}
fs.writeMultiFiles = function (filenames, datastrs, callback) {
postsomething('name=' + filenames.join(';') + '&value=' + datastrs.join(';'), '/writeMultiFiles', callback);
}
fs.readdir = function (path, callback) {
//callback:function(err, data)
//path:支持"/"做分隔符,不以"/"结尾
//data:[filename1,filename2,..] filename是字符串,只包含文件不包含目录
if (typeof (path) != typeof (''))
throw 'Type Error in fs.readdir';
var data = '';
data += 'name=' + path;
postsomething(data, '/listFile', function (err, data) {
try {
data = JSON.parse(data);
} catch (e) {
err = "Invalid /listFile";
data = null;
}
callback(err, data);
});
return;
}
/**
* @param {string} path 支持"/"做分隔符
* @param {() => {err: string, data}} callback
*/
fs.mkdir = function (path, callback) {
//callback:function(err, data)
if (typeof (path) != typeof (''))
throw 'Type Error in fs.readdir';
var data = '';
data += 'name=' + path;
postsomething(data, '/makeDir', callback);
return;
}
/**
* @param {string} path 支持"/"做分隔符, 不以"/"结尾
* @param {() => {err: string, data}} callback
*/
fs.moveFile = function (src, dest, callback) {
if (typeof (src) != typeof ('') || typeof (dest) != typeof (''))
throw 'Type Error in fs.readdir';
var data = '';
data += 'src=' + src + "&dest=" + dest;
postsomething(data, '/moveFile', callback);
return;
}
/**
* @param {string} path 支持"/"做分隔符, 不以"/"结尾
* @param {() => {err: string, data}} callback
*/
fs.deleteFile = function (path, callback) {
if (typeof (path) != typeof (''))
throw 'Type Error in fs.readdir';
var data = '';
data += 'name=' + path;
postsomething(data, '/deleteFile', callback);
return;
}
})();

70
_server/fsTest_cs.html Normal file
View File

@ -0,0 +1,70 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script src="./fs.js"></script>
<script>
fs.writeFile('_test.txt', '123中a文bc', 'utf-8', function (e, d) {
console.log(e, d);
})
setTimeout(function () {
fs.writeFile('_test_bin.txt', 'abc=', 'base64', function (e, d) {
console.log(e, d);
})
}, 1000);
setTimeout(function () {
fs.readFile('_test.txt', 'utf-8', function (e, d) {
console.log(e, d);
})
}, 2000);
setTimeout(function () {
fs.readFile('_test_bin.txt', 'base64', function (e, d) {
console.log(e, d);
})
}, 3000);
setTimeout(function () {
fs.readdir('.', function (e, d) {
console.log(e, d);
})
}, 4000);
setTimeout(function () {
fs.writeMultiFiles(['_test.txt','_test_multi.txt'], ['abc=','abe='], function (e, d) {
console.log(e, d);
})
}, 5000);
setTimeout(function () {
fs.mkdir('__test__', function (e, d) {
console.log(e, d);
})
}, 6000);
setTimeout(function () {
fs.moveFile('_test_bin.txt', '__test__/_test_bin.txt', function (e, d) {
console.log(e, d);
})
}, 7000);
setTimeout(function () {
fs.moveFile('_test.txt', '__test__/_test.txt', function (e, d) {
console.log(e, d);
})
}, 8000);
setTimeout(function () {
fs.moveFile('_test_multi.txt', '__test__/_test.txt', function (e, d) {
console.log(e, d);
})
}, 8000);
setTimeout(function () {
fs.deleteFile('__test__/_test_bin.txt', function (e, d) {
console.log(e, d);
})
}, 9000);
setTimeout(function () {
fs.deleteFile('__test__', function (e, d) {
console.log(e, d);
})
}, 10000);
</script>
</body>
</html>

BIN
_server/img_md/view1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 669 KiB

BIN
_server/img_md/view2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 KiB

BIN
_server/img_md/view3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

136
_server/refactoring.md Normal file
View File

@ -0,0 +1,136 @@
# 重构
> 目前状态: 按功能分类, 维持稳定状态, 在3.0中重写
总体思路
+ 按功能拆分文件
+ 左侧页面模块化, 方便添加
+ 不同的模式的文件操作尽可能模块化
目前主要在重构editor_file, 思路是editor.file负责把editor.game内的游戏数据格式化成字符串以及写入到文件, 由editor.game来修改数据
+ editor.file维护一些标记, 描述哪些数据需要格式化并写入, 在save时写入文件(自动保存的话就是每次修改数据都触发save)
+ editor.game修改数据, 并修改editor.file中的标记
+ 此思路下editor.file的大部分内容会挪到editor.game, editor.game和editor.table可能会再进一步合并拆分
editor_file之后是更改editor.map的储存方式, 现有的存对象的模式要在对象和数字间来回转换, 非常繁琐和奇怪
## 文件结构
(全部小写,必要时用下划线分割)
+ [ ] editor_blockly 图块化事件编辑器
+ [ ] editor_multi 多行文本编辑器
+ [x] editor_table 处理表格的生成, 及其响应的事件, 从原editor\_mode中分离
+ [ ] editor_file 调用fs.js编辑文件, 把原editor\_file模块化, 并且只负责文件写入
+ [ ] editor_game 处理游戏数据, 导入为editor的数据, 编辑数据, 从原editor和editor_file中抽离. **只有此文件允许`\s(main|core)`形式的调用**(以及其初始化`editor_game_wrapper(editor, main, core);`)
+ [x] editor_util 生成guid/处理颜色 等函数, 从editor分离
+ [ ] editor_listen 处理界面上的按钮/下拉框点击等用户的操作与功能函数的绑定, 维护editor.dom, unsorted_1/2中的绑定挪到此处, 其中的函数内容, 分类放在其他文件
+ [ ] editor_mappanel 与地图区相关的功能, <-unsorted_1/2/3
+ [ ] editor_datapanel 与数据区相关的功能, <-unsorted_1/2/3
+ [ ] editor_materialpanel 与素材区相关的功能, <-unsorted_1/2/3
+ [ ] editor_ui 维护printe/printf/tip, 以及之后可能的窗口化, ui事件中没有具体到前三个区中的函数 <-unsorted_1/2/3
+ [ ] editor 执行初始化流程加组合各组件
+ [ ] 原editor_mode 移除
+ [x] 原vm 移除
+ [x] \*comment.js 表格注释与结构, 移至table/\*comment.js
## 对象结构
```
editor: {
__proto__: {
fs
util
file
table
multi
blockly
game
}
config: 编辑器配置
mode: 当前的模式(左侧的选择)
map: 当前编辑层的地图
isMobile: 编辑器是否是手机端
currentFloorData: 当前编辑的楼层数据
...
}
```
---
## 某些注意到的点&准备修改的内容
+ 插入公共事件的参数的转义处理, .g4中添加ObjectString, 要求其中的值可以JSON.parse, 生成的code中也是作为对象而不是字符串出现
+ 修改editor.multi中的转义处理, 目前双击某些方块使用文本编辑的处理, 一部分在editor.blockly, 一部分在editor.multi, 比较混乱
+ 地图的编辑与其他(如全塔属性和楼层属性), 现在的文件操作的模式是完全不同的
楼层文件的储存与其他不同
+ [x] editor.file在修改时不再返回obj和commentobj,只在查询时返回
+ editor.file中的各个条目, 非常相似, 但是细节的不同处理非常麻烦. 是类似的代码复制后修改一部分, 尝试模块化(或者重写)
+ functions和plugins的借助JSON.stringify的replacer特殊处理, 与其他项的处理完全不同, 改成用统一的方法处理(为了统一,全部使用这种不直观的replacer的处理)
+ 怪物/物品/地图选点事件的处理, field中怪物id等明显与其他节地位不等, 处理起来很繁琐
+ 目前editor.map中储存的是info\<object\>, 准备改为和core一致只储存数字
+ editor.widthX特别不直观
+ ? 编辑器使用可拖拽和调大小的窗口做容器
## 功能改进
+ [x] 大地图
在切换时, 每次都回到最左上->每个楼层记录一个位置
四个箭头支持长按
? 滚动条
+ [ ] ? 表格折叠
变为四栏, 可以折叠展开
+ [x] blockly对于无法识别的图块原样返回
+ [ ] ? 简洁的事件方块注册
`editor.registerEvent('log',[['test','Int','测试',0],['floorId','Idstring','楼层','MT0']])`
+ [x] 一个显示所有快捷键的文本
+ [x] 更多快捷键
【全塔属性】、【楼层属性】等常用的编辑栏切换
+ [x] ? 地图编辑优化
常用的地图编辑快捷键/命令复制ctrl+c、粘贴ctrl+v、复制可绑定为现在的“选中xx位置事件” 粘贴为复制xx事件到此处撤回ctrl+z、取消撤回ctrl+y
可以按住拖动图块与事件。
+ [ ] ? 自由建立快捷键到命令的注册表。
+ [ ] 画地图也自动保存
+ [x] 修改系统的触发器(下拉菜单增加新项)
在编辑器修改`comment.js`现场发readFile请求读文件然后开脚本编辑器进行编辑
+ [x] ? 删除注册项/修改图块ID
+ [ ] ? 怪物和道具也能像其他类型那样查看“图块信息”(而不只是具体的怪物属性)
+ [x] 素材区自动换列
怪物或道具太多时, 按照每100个进行拆分新开列来显示
+ [x] 多帧素材只显示第一帧
+ [x] `显示文章`以及`选项`等方块, 把`标题`和`图像`从字符串提取出填回相应的空
+ [x] blockly中某些需要选点的填空, 增加按钮, 点击后从缩略图中点击位置
+ [ ] 插件编写增加判定,如果保存时框内不是以 "function\s*()" 开头(也就是用户直接写的脚本),则自动添加一个 function() { } 将代码包装起来。
## 左侧页面模式
标题? 保存按钮? 添加按钮? 删除按钮?
自定义内容?
表格?

791
_server/table/comment.js Normal file
View File

@ -0,0 +1,791 @@
/*
* 表格配置项
* 在这里可以对表格中的各项显示进行配置包括表格项提示内容等内容具体写法照葫芦画瓢即可
* 本配置项包括道具怪物图块属性楼层属性等内容
* 相关文档 _docs/editor.md ~ http://127.0.0.1:1055/_docs/#/editor?id=修改表格
*/
var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
"_type": "object",
"_data": {
// --------------------------- 【道具】相关的表格配置 --------------------------- //
"items": {
"_type": "object",
"_data": {
"id": {
"_leaf": true,
"_type": "disable",
"_docs": "道具ID",
"_data": "道具ID可于页面底部修改"
},
"cls": {
"_leaf": true,
"_type": "select",
"_select": {
"values": [
"items",
"constants",
"tools",
"equips"
]
},
"_docs": "道具类别",
"_data": "items(宝石、血瓶) constants(永久物品) tools(消耗道具) equips(装备)"
},
"name": {
"_leaf": true,
"_type": "textarea",
"_string": true,
"_data": "道具名称"
},
"text": {
"_leaf": true,
"_type": "textarea",
"_string": true,
"_docs": "道具描述",
"_data": "道具在道具栏中显示的描述"
},
"hideInToolbox": {
"_leaf": true,
"_type": "checkbox",
"_docs": "不显示在道具栏",
},
"equip": {
"_leaf": true,
"_type": "event",
"_event": "equip",
"_docs": "道具的装备属性"
},
"hideInReplay": {
"_leaf": true,
"_type": "checkbox",
"_docs": "回放不绘制道具栏",
"_data": "此项建议在会频繁连续多次使用的道具开启(如开启技能,或者《镜子》那样的镜像切换等等)"
},
"itemEffect": {
"_leaf": true,
"_type": "textarea",
"_string": true,
"_lint": true,
"_docs": "即捡即用效果",
"_data": "即捡即用类物品的效果仅对cls为items有效。"
},
"itemEffectTip": {
"_leaf": true,
"_type": "textarea",
"_string": true,
"_docs": "即捡即用提示",
"_data": "即捡即用类物品在获得时提示的文字仅对cls为items有效。"
},
"useItemEvent": {
"_leaf": true,
"_type": "event",
"_event": "item",
"_docs": "碰触或使用事件",
"_data": "碰触或使用本道具所执行的事件对所有cls有效"
},
"useItemEffect": {
"_leaf": true,
"_type": "textarea",
"_string": true,
"_lint": true,
"_docs": "使用效果",
"_data": "道具效果仅对cls为tools或constants有效。"
},
"canUseItemEffect": {
"_leaf": true,
"_type": "textarea",
"_string": true,
"_lint": true,
"_docs": "能否使用或装备",
"_data": "当前能否使用或装备该道具仅对cls不为items有效。null表示始终不可使用但可装备"
}
}
},
"items_template": { 'cls': 'items', 'name': '新物品', 'canUseItemEffect': 'true' },
// --------------------------- 【怪物】相关的表格配置 --------------------------- //
"enemys": {
"_type": "object",
"_data": {
"id": {
"_leaf": true,
"_type": "disable",
"_docs": "怪物ID",
"_data": "怪物ID可于页面底部修改"
},
"name": {
"_leaf": true,
"_type": "textarea",
"_string": true,
"_data": "名称"
},
"description": {
"_leaf": true,
"_type": "textarea",
"_string": true,
"_docs": "怪物描述",
"_data": "可在怪物详细信息页面写的怪物描述,支持颜色、字体大小和样式、粗体斜体等转义方式。"
},
"displayIdInBook": {
"_leaf": true,
"_type": "textarea",
"_string": true,
"_docs": "手册ID",
"_data": "在怪物手册中映射到的怪物ID。如果此项不为null则在怪物手册中将用目标ID来替换该怪物原本的ID。常被运用在同一个怪物的多朝向上。"
},
"faceIds": {
"_leaf": true,
"_type": "event",
"_event": "faceIds",
"_docs": "行走朝向",
"_data": "行走图朝向。在勇士撞上图块时,或图块在移动时,会自动选择最合适的朝向图块(如果存在定义)来进行绘制。"
},
"bigImage": {
"_leaf": true,
"_type": "material",
"_directory": "./project/images/:images",
"_transform": (function (one) {
if (one.endsWith('.png')) return one;
return null;
}).toString(),
"_onconfirm": (function (previous, current) {
if (current.length == 0) return null;
return current[0];
}).toString(),
"_docs": "绑定贴图",
"_data": "该怪物绑定的怪物贴图,用法详见文档"
},
"hp": {
"_leaf": true,
"_type": "textarea",
"_data": "生命值"
},
"atk": {
"_leaf": true,
"_type": "textarea",
"_data": "攻击力"
},
"def": {
"_leaf": true,
"_type": "textarea",
"_data": "防御力"
},
"money": {
"_leaf": true,
"_type": "textarea",
"_data": "金币"
},
"exp": {
"_leaf": true,
"_type": "textarea",
"_data": "经验"
},
"point": {
"_leaf": true,
"_type": "textarea",
"_data": "加点"
},
"special": {
"_leaf": true,
"_type": "popCheckboxSet",
"_checkboxSet": function () {
var array = functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a.enemys.getSpecials()
var b = [],
c = [];
for (var index = 0; index < array.length; index++) {
b.push(array[index][0])
var name = array[index][1];
if (name instanceof Function) name = name({});
c.push(name + "(" + array[index][0] + ")")
}
return {
"prefix": c,
"key": b
}
},
"_data": "特殊属性"
},
"value": {
"_leaf": true,
"_type": "textarea",
"_docs": "特殊属性数值",
"_data": "特殊属性的数值\n如领域/阻激/激光怪的伤害值;光环怪增加生命的比例"
},
"zone": {
"_leaf": true,
"_type": "textarea",
"_docs": "领域伤害",
"_data": "领域怪的伤害值"
},
"repulse": {
"_leaf": true,
"_type": "textarea",
"_docs": "阻击伤害",
"_data": "阻击怪的伤害值"
},
"laser": {
"_leaf": true,
"_type": "textarea",
"_docs": "激光伤害",
"_data": "激光怪的伤害值"
},
"breakArmor": {
"_leaf": true,
"_type": "textarea",
"_docs": "破甲比例",
"_data": "破甲百分比"
},
"counterAttack": {
"_leaf": true,
"_type": "textarea",
"_docs": "反击比例",
"_data": "反击百分比"
},
"vampire": {
"_leaf": true,
"_type": "textarea",
"_docs": "吸血比例",
"_data": "吸血怪的吸血百分比"
},
"hpBuff": {
"_leaf": true,
"_type": "textarea",
"_docs": "光环加血",
"_data": "光环怪增加生命的比例"
},
"atkBuff": {
"_leaf": true,
"_type": "textarea",
"_docs": "光环加攻",
"_data": "光环怪增加攻击的比例"
},
"defBuff": {
"_leaf": true,
"_type": "textarea",
"_docs": "光环加防",
"_data": "光环怪增加防御的比例"
},
"zoneSquare": {
"_leaf": true,
"_type": "checkbox",
"_docs": "九宫格",
"_data": "领域、阻击或捕捉怪是否九宫格"
},
"haloSquare": {
"_leaf": true,
"_type": "checkbox",
"_docs": "九宫格",
"_data": "光环怪是否九宫格"
},
"range": {
"_leaf": true,
"_type": "textarea",
"_range": "(thiseval==~~thiseval && thiseval>0)||thiseval==null",
"_docs": "领域范围",
"_data": "领域的范围不加默认为1"
},
"haloRange": {
"_leaf": true,
"_type": "textarea",
"_range": "(thiseval==~~thiseval && thiseval>0)||thiseval==null",
"_docs": "光环范围",
"_data": "光环的范围;不加为全图效果"
},
"notBomb": {
"_leaf": true,
"_type": "checkbox",
"_docs": "不可炸",
"_data": "该怪物不可被炸"
},
"n": {
"_leaf": true,
"_type": "textarea",
"_range": "(thiseval==~~thiseval && thiseval>0)||thiseval==null",
"_docs": "连击数",
"_data": "多连击的连击数,净化怪的净化倍率"
},
"purify": {
"_leaf": true,
"_type": "textarea",
"_range": "(thiseval==~~thiseval && thiseval>0)||thiseval==null",
"_docs": "净化倍率",
"_data": "净化百分比"
},
"add": {
"_leaf": true,
"_type": "checkbox",
"_docs": "吸血加到自身",
"_data": "吸血后是否加到自身"
},
"haloAdd": {
"_leaf": true,
"_type": "checkbox",
"_docs": "光环是否叠加",
"_data": "光环是否叠加"
},
"atkValue": {
"_leaf": true,
"_type": "textarea",
"_range": "thiseval==~~thiseval||thiseval==null",
"_docs": "退化扣攻",
"_data": "退化时勇士下降的攻击力点数"
},
"defValue": {
"_leaf": true,
"_type": "textarea",
"_range": "thiseval==~~thiseval||thiseval==null",
"_docs": "退化扣防",
"_data": "退化时勇士下降的防御力点数"
},
"damage": {
"_leaf": true,
"_type": "textarea",
"_range": "thiseval==~~thiseval||thiseval==null",
"_docs": "固伤",
"_data": "战前扣血的点数"
},
"beforeBattle": {
"_leaf": true,
"_type": "event",
"_event": "beforeBattle",
"_docs": "战前事件",
"_data": "和该怪物战斗前触发的事件列表"
},
"afterBattle": {
"_leaf": true,
"_type": "event",
"_event": "afterBattle",
"_docs": "战后事件",
"_data": "和该怪物战斗后触发的事件列表"
}
}
},
"enemys_template": { 'name': '新敌人', 'hp': 0, 'atk': 0, 'def': 0, 'money': 0, 'exp': 0, 'point': 0, 'special': [] },
// --------------------------- 【图块属性】相关的表格配置 --------------------------- //
"maps": {
"_type": "object",
"_data": {
"id": {
"_leaf": true,
"_type": "disable",
"_range": "false",
"_docs": "图块ID",
"_data": "图块唯一ID可在页面底部修改"
},
"idnum": {
"_leaf": true,
"_type": "disable",
"_range": "false",
"_data": "图块数字"
},
"cls": {
"_leaf": true,
"_type": "disable",
"_range": "false",
"_data": "图块类别"
},
"name": {
"_leaf": true,
"_type": "textarea",
"_string": true,
"_data": "图块名称"
},
"trigger": {
"_leaf": true,
"_type": "select",
"_select": {
"values": [
null,
"openDoor",
"pushBox",
"ski",
"custom"
]
},
"_docs": "触发器",
"_data": "该图块的默认触发器"
},
"canPass": {
"_leaf": true,
"_type": "checkbox",
"_docs": "可通行性",
},
"script": {
"_leaf": true,
"_type": "textarea",
"_string": true,
"_lint": true,
"_docs": "碰触脚本",
"_data": "触碰到该图块时自动执行的脚本内容;此脚本会在该点的触发器执行前执行"
},
"event": {
"_leaf": true,
"_type": "event",
"_event": "item",
"_docs": "碰触事件",
"_data": "触碰到该图块时自动执行的事件内容;如果存在本事件则不会执行默认触发器"
},
"cannotOut": {
"_leaf": true,
"_type": "checkboxSet",
"_checkboxSet": {
"prefix": ["上: ", "下: ", "<br>左: ", "右: "],
"key": ["up", "down", "left", "right"]
},
"_docs": "不可出方向",
"_data": "该图块的不可出方向\n对背景层、事件层、前景层上的图块均有效"
},
"cannotIn": {
"_leaf": true,
"_type": "checkboxSet",
"_checkboxSet": {
"prefix": ["上: ", "下: ", "<br>左: ", "右: "],
"key": ["up", "down", "left", "right"]
},
"_docs": "不可入方向",
"_data": "该图块的不可入方向\n对背景层、事件层、前景层上的图块均有效"
},
"canBreak": {
"_leaf": true,
"_type": "checkbox",
"_docs": "可破震",
"_data": "该图块是否可被破墙或地震"
},
"animate": {
"_leaf": true,
"_type": "select",
"_select": {
"values": [null, 1, 2, 3, 4],
},
"_docs": "动画帧数",
"_data": "null代表素材默认帧数"
},
"doorInfo": {
"_leaf": true,
"_type": "event",
"_event": "doorInfo",
"_docs": "门信息",
"_data": "该图块的门信息仅对animates和npc48生效。"
},
"faceIds": {
"_leaf": true,
"_type": "event",
"_event": "faceIds",
"_docs": "行走图朝向",
"_data": "行走图朝向。在勇士撞上图块时,或图块在移动时,会自动选择最合适的朝向图块(如果存在定义)来进行绘制。"
},
"bigImage": {
"_leaf": true,
"_type": "material",
"_directory": "./project/images/:images",
"_transform": (function (one) {
if (one.endsWith('.png')) return one;
return null;
}).toString(),
"_onconfirm": (function (previous, current) {
if (current.length == 0) return null;
return current[0];
}).toString(),
"_docs": "绑定贴图",
"_data": "该图块绑定的贴图,用法详见文档"
}
}
},
// --------------------------- 【楼层属性】相关的表格配置 --------------------------- //
"floors": {
"_type": "object",
"_data": {
"floor": {
"_type": "object",
"_data": {
"floorId": {
"_leaf": true,
"_type": "disable",
"_range": "false",
"_docs": "楼层ID",
"_data": "文件名和floorId需要保持完全一致可在页面底部修改"
},
"title": {
"_leaf": true,
"_type": "textarea",
"_docs": "楼层名",
"_data": "楼层中文名,将在切换楼层和浏览地图时显示"
},
"name": {
"_leaf": true,
"_type": "textarea",
"_docs": "状态栏显示",
"_data": "显示在状态栏中的层数"
},
"width": {
"_leaf": true,
"_type": "disable",
"_range": "false",
"_docs": "宽度",
"_data": "地图x方向大小,请在表格最下方修改"
},
"height": {
"_leaf": true,
"_type": "disable",
"_range": "false",
"_docs": "高度",
"_data": "地图y方向大小,请在表格最下方修改"
},
"canFlyTo": {
"_leaf": true,
"_type": "checkbox",
"_docs": "可楼传飞到",
"_data": "该楼能否被楼传器飞到"
},
"canFlyFrom": {
"_leaf": true,
"_type": "checkbox",
"_docs": "可楼传飞出",
"_data": "该楼能否用楼传器飞出"
},
"canUseQuickShop": {
"_leaf": true,
"_type": "checkbox",
"_docs": "快捷商店",
"_data": "该层是否允许使用快捷商店"
},
"cannotViewMap": {
"_leaf": true,
"_type": "checkbox",
"_docs": "不可浏览",
"_data": "该层是否不允许被浏览地图看到;如果勾上则浏览地图会跳过该层"
},
"cannotMoveDirectly": {
"_leaf": true,
"_type": "checkbox",
"_docs": "不可瞬移",
"_data": "该层是否不允许瞬间移动;如果勾上则不可在此层进行瞬移"
},
"underGround": {
"_leaf": true,
"_type": "checkbox",
"_docs": "地下层",
"_data": "是否是地下层如果该项为true则同层传送将传送至上楼梯"
},
"firstArrive": {
"_leaf": true,
"_type": "event",
"_event": "firstArrive",
"_docs": "首次到达事件",
"_data": "第一次到该楼层触发的事件,可以双击进入事件编辑器。"
},
"eachArrive": {
"_leaf": true,
"_type": "event",
"_event": "eachArrive",
"_docs": "每次到达事件",
"_data": "每次到该楼层触发的事件可以双击进入事件编辑器该事件会在firstArrive执行后再执行。"
},
"parallelDo": {
"_leaf": true,
"_type": "textarea",
"_string": true,
"_lint": true,
"_template": "(function (timestamp) {\\n\\t// 在这里写楼层并行脚本大约每16.6ms执行一次\\n\\t// timestamp: 从游戏开始到当前所经过的毫秒数。\\n\\t\\n})(timestamp);",
"_docs": "并行处理脚本",
"_data": "在该层楼时执行的并行脚本处理。\n可以在这里写上任意需要自动执行的脚本比如打怪自动开门等。\n详见文档-事件-并行事件处理。"
},
"upFloor": {
"_leaf": true,
"_type": "point",
"_range": "thiseval==null||((thiseval instanceof Array) && thiseval.length==2)",
"_docs": "上楼点",
"_data": "该层上楼点,如[2,3]。\n如果此项不为null则楼层转换时的stair:upFloor以及楼传器的落点会被替换成该点而不是该层的上楼梯。"
},
"downFloor": {
"_leaf": true,
"_type": "point",
"_range": "thiseval==null||((thiseval instanceof Array) && thiseval.length==2)",
"_docs": "下楼点",
"_data": "该层下楼点,如[2,3]。\n如果此项不为null则楼层转换时的stair:downFloor以及楼传器的落点会被替换成该点而不是该层的下楼梯。"
},
"flyPoint": {
"_leaf": true,
"_type": "point",
"_range": "thiseval==null||((thiseval instanceof Array) && thiseval.length==2)",
"_docs": "楼传落点",
"_data": "该层楼传落点,如[2,3]。\n如果此项不为null则楼层飞行器强行落到此点无视上下楼或平面塔属性。"
},
"defaultGround": {
"_leaf": true,
"_type": "textarea",
"_docs": "地面图块",
"_data": "默认地面的图块ID此项修改后需要刷新才能看到效果。不填则默认是ground"
},
"images": {
"_leaf": true,
"_type": "event",
"_event": "floorImage",
"_docs": "楼层贴图"
},
"color": {
"_leaf": true,
"_type": "color",
"_docs": "色调",
"_data": "该层的默认画面色调。本项可不写代表无色调如果写需要是一个RGBA数组如[255,0,0,0.3]"
},
"weather": {
"_leaf": true,
"_type": "textarea",
"_docs": "天气",
"_data": "该层的默认天气。本项可忽略表示晴天,如果写则第一项为\"rain\"\"snow\", \"sun\", \"fog\", \"cloud\“代表对应的天气第二项为1-10之间的数代表强度。\n如[\"rain\", 8]代表8级雨天。"
},
"bgm": {
"_leaf": true,
"_type": "material",
"_directory": "./project/bgms/",
"_transform": (function (one) {
if (one.endsWith('.mp3') || one.endsWith('.ogg') || one.endsWith('.wav') || one.endsWith('.m4a') || one.endsWith('.flac'))
return one;
return null;
}).toString(),
"_onconfirm": (function (previous, current) {
if (current.length == 0) return null;
if (current.length == 1) return current[0];
return current;
}).toString(),
"_docs": "背景音乐",
"_data": "到达该层后默认播放的BGM"
},
"ratio": {
"_leaf": true,
"_type": "textarea",
"_range": "thiseval <= Number.MAX_SAFE_INTEGER && thiseval>=0",
"_docs": "宝石血瓶效果",
"_data": "每一层的宝石/血瓶效果,即获得宝石和血瓶时框内\"ratio\"的值。"
}
}
},
"loc": {
"_type": "object",
"_data": {
"events": {
"_leaf": true,
"_type": "event",
"_event": "event",
"_docs": "普通事件",
"_data": "该点的可能事件列表,可以双击进入事件编辑器。"
},
"autoEvent": {
"_type": "object",
"_leaf": false,
"_action": function (args) {
args.vobj = args.vobj || {};
for (var ii = 0; ii < 2; ii++) {
args.vobj[ii] = args.vobj[ii] || null;
}
},
"_data": function (key) {
return {
"_leaf": true,
"_type": "event",
"_event": "autoEvent",
"_data": "自动事件"
}
}
},
"changeFloor": {
"_leaf": true,
"_type": "event",
"_event": "changeFloor",
"_docs": "楼层转换",
"_data": "该点楼层转换事件该事件不能和上面的events同时出现否则会被覆盖"
},
"beforeBattle": {
"_leaf": true,
"_type": "event",
"_event": "beforeBattle",
"_docs": "战前事件",
"_data": "该点战斗前可能触发的事件列表,可以双击进入事件编辑器。"
},
"afterBattle": {
"_leaf": true,
"_type": "event",
"_event": "afterBattle",
"_docs": "战后事件",
"_data": "该点战斗后可能触发的事件列表,可以双击进入事件编辑器。"
},
"afterGetItem": {
"_leaf": true,
"_type": "event",
"_event": "afterGetItem",
"_docs": "道具后事件",
"_data": "该点获得道具后可能触发的事件列表,可以双击进入事件编辑器。"
},
"afterOpenDoor": {
"_leaf": true,
"_type": "event",
"_event": "afterOpenDoor",
"_docs": "开门后事件",
"_data": "该点开完门后可能触发的事件列表,可以双击进入事件编辑器。"
},
"cannotMove": {
"_leaf": true,
"_type": "checkboxSet",
"_checkboxSet": {
"prefix": ["上: ", "下: ", "<br>左: ", "右: "],
"key": ["up", "down", "left", "right"]
},
"_docs": "不可出方向",
"_data": "该点不可通行出的方向 \n 可以在这里定义该点不能前往哪个方向,可以达到悬崖之类的效果"
},
"cannotMoveIn": {
"_leaf": true,
"_type": "checkboxSet",
"_checkboxSet": {
"prefix": ["上: ", "下: ", "<br>左: ", "右: "],
"key": ["up", "down", "left", "right"]
},
"_docs": "不可入方向",
"_data": "该点不可通行入的方向 \n 可以在这里定义从哪个方向前往该点,可以达到悬崖之类的效果"
},
}
}
}
},
"floors_template": {
"floorId": "to be covered",
"title": "new floor",
"name": "new floor",
"width": 13,
"height": 13,
"canFlyTo": true,
"canFlyFrom": true,
"canUseQuickShop": true,
"cannotViewMap": false,
"cannotMoveDirectly": false,
"images": [],
"ratio": 1,
"defaultGround": "ground",
"bgm": null,
"upFloor": null,
"downFloor": null,
"color": null,
"weather": null,
"firstArrive": [],
"eachArrive": [],
"parallelDo": "",
"events": {},
"changeFloor": {},
"beforeBattle": {},
"afterBattle": {},
"afterGetItem": {},
"afterOpenDoor": {},
"autoEvent": {},
"cannotMove": {},
"cannotMoveIn": {}
}
}
}

View File

@ -0,0 +1,678 @@
/*
* 表格配置项
* 在这里可以对表格中的各项显示进行配置包括表格项提示内容等内容具体写法照葫芦画瓢即可
* 本配置项包括全塔属性的配置项
* 相关文档 _docs/editor.md ~ http://127.0.0.1:1055/_docs/#/editor?id=修改表格
*/
var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
"_type": "object",
"_data": {
"main": {
"_type": "object",
"_data": {
"floorIds": {
"_leaf": true,
"_type": "textarea",
"_range": "editor.mode.checkFloorIds(thiseval)",
"_docs": "楼层列表",
"_data": "在这里按顺序放所有的楼层;其顺序直接影响到楼层传送器、浏览地图和上/下楼器的顺序"
},
"floorPartitions": {
"_leaf": true,
"_type": "event",
"_event": "floorPartition",
"_docs": "分区指定",
"_data": "可以在这里指定楼层分区;主要适用于不可返回的高层塔;进入新分区后将自动调用砍层插件以减少空间消耗;未在任何分区的楼层将被视为公共区域"
},
"images": {
"_leaf": true,
"_type": "material",
"_range": "editor.mode.checkImages(thiseval, './project/images/')",
"_directory": "./project/images/",
"_transform": (function (one) {
if (one.endsWith('.png') || one.endsWith('.jpg') || one.endsWith('.jpeg') || one.endsWith('.gif'))
return one;
return null;
}).toString(),
"_docs": "使用图片",
"_data": "在此存放所有可能使用的图片tilesets除外 \n图片可以被作为背景图的一部分也可以直接用自定义事件进行显示。 \n 图片名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 \n 建议对于较大的图片,在网上使用在线的“图片压缩工具(http://compresspng.com/zh/)”来进行压缩,以节省流量 \n 依次向后添加",
},
"splitImages": {
"_leaf": true,
"_type": "event",
"_event": "splitImages",
"_docs": "图片切分",
"_data": "可以在这里对使用到的图片进行按照一定宽高切分,生成若干新的小图供使用"
},
"tilesets": {
"_leaf": true,
"_type": "material",
"_range": "editor.mode.checkImages(thiseval, './project/tilesets/')",
"_directory": "./project/tilesets/",
"_transform": (function (one) {
if (one.endsWith('.png'))
return one;
return null;
}).toString(),
"_onconfirm": (function (previous, current) {
// 额外素材是有序的,因此根据之前的内容进行排序,然后在之后追加新的
previous = previous || [];
current = current.sort(function (a, b) {
var i = previous.indexOf(a);
var j = previous.indexOf(b);
if (i >= 0 && j >= 0) return i - j;
return j >= 0 ? 1 : -1;
});
return core.subarray(current, previous) == null &&
!confirm("您修改了现有额外素材的内容或顺序,这可能导致已经使用的额外素材无法正确显示。确定要修改么?") ?
previous : current;
}).toString(),
"_docs": "额外素材",
"_data": "在此存放额外素材的图片名, \n可以自定导入任意张素材图片无需PS无需注册即可直接在游戏中使用 \n 形式如[\"1.png\", \"2.png\"] ,将需要的素材图片放在images目录下 \n 素材的宽高必须都是32的倍数且图片上的总图块数不超过1000即最多有1000个32*32的图块在该图片上"
},
"animates": {
"_leaf": true,
"_type": "material",
"_range": "editor.mode.checkUnique(thiseval)",
"_directory": "./project/animates/",
"_transform": (function (one) {
if (one.endsWith(".animate")) return one.substring(0, one.lastIndexOf('.'));
return null;
}).toString(),
"_docs": "使用动画",
"_data": "在此存放所有可能使用的动画必须是animate格式在这里不写后缀名 \n动画必须放在animates目录下文件名不能使用中文不能带空格或特殊字符 \n \"jianji\", \"thunder\" 根据需求自行添加"
},
"bgms": {
"_leaf": true,
"_type": "material",
"_range": "editor.mode.checkUnique(thiseval)",
"_directory": "./project/bgms/",
"_transform": (function (one) {
if (one.endsWith('.mp3') || one.endsWith('.ogg') || one.endsWith('.wav') || one.endsWith('.m4a') || one.endsWith('.flac'))
return one;
return null;
}).toString(),
"_docs": "使用音乐",
"_data": "在此存放所有的bgm和文件名一致。 \n音频名不能使用中文不能带空格或特殊字符可以直接改名拼音就好"
},
"sounds": {
"_leaf": true,
"_type": "material",
"_range": "editor.mode.checkUnique(thiseval)",
"_directory": "./project/sounds/",
"_transform": (function (one) {
if (one.endsWith('.mp3') || one.endsWith('.ogg') || one.endsWith('.wav') || one.endsWith('.m4a') || one.endsWith('.flac'))
return one;
return null;
}).toString(),
"_docs": "使用音效",
"_data": "在此存放所有的SE和文件名一致 \n音频名不能使用中文不能带空格或特殊字符可以直接改名拼音就好"
},
"fonts": {
"_leaf": true,
"_type": "material",
"_range": "editor.mode.checkUnique(thiseval)",
"_directory": "./project/fonts/",
"_transform": (function (one) {
if (one.endsWith(".ttf")) return one.substring(0, one.lastIndexOf('.'));
return null;
}).toString(),
"_docs": "使用字体",
"_data": "在此存放所有可能使用的字体 \n 字体名不能使用中文,不能带空格或特殊字符"
},
"nameMap": {
"_leaf": true,
"_type": "event",
"_event": "nameMap",
"_docs": "文件别名",
"_data": "文件别名设置目前仅对images, animates, bgms, sounds有效。"
},
"levelChoose": {
"_leaf": true,
"_type": "event",
"_event": "levelChoose",
"_docs": "难度分歧",
"_data": "难度分歧定义和对应的事件;此处留空数组表示将直接开始游戏"
},
"equipName": {
"_leaf": true,
"_type": "textarea",
"_range": "(thiseval instanceof Array)||thiseval==null",
"_docs": "装备孔",
"_data": "装备位名称为一个数组此项的顺序与equiptype数值关联例如可写[\"武器\",\"防具\",\"首饰\"]等等。"
},
"startBgm": {
"_leaf": true,
"_type": "material",
"_directory": "./project/bgms/",
"_transform": (function (one) {
if (one.endsWith('.mp3') || one.endsWith('.ogg') || one.endsWith('.wav') || one.endsWith('.m4a') || one.endsWith('.flac'))
return one;
return null;
}).toString(),
"_onconfirm": (function (previous, current) {
if (current.length == 0) return null;
return current[0];
}).toString(),
"_docs": "标题音乐",
"_data": "在标题界面应该播放的bgm内容"
},
"styles": {
"_leaf": true,
"_type": "event",
"_event": "mainStyle",
"_docs": "主样式",
"_data": "主要样式设置,包括标题、按钮、状态栏等的背景色等"
}
}
},
"firstData": {
"_type": "object",
"_data": {
"title": {
"_leaf": true,
"_type": "textarea",
"_string": true,
"_docs": "游戏名",
"_data": "游戏名,将显示在标题页面以及切换楼层的界面中"
},
"name": {
"_leaf": true,
"_type": "textarea",
"_string": true,
"_range": "/^[a-zA-Z0-9_]{1,30}$/.test(thiseval)",
"_docs": "唯一英文标识符",
"_data": "游戏的唯一英文标识符。由英文、数字、下划线组成不能超过30个字符。\n此项必须修改其将直接影响到存档的定位"
},
"version": {
"_leaf": true,
"_type": "textarea",
"_string": true,
"_docs": "游戏版本",
"_data": "当前游戏版本;版本不一致的存档不能通用。"
},
"floorId": {
"_leaf": true,
"_type": "select",
"_select": {
"values": data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.main.floorIds
},
"_range": "data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.main.floorIds.indexOf(thiseval)!==-1",
"_docs": "初始楼层",
"_data": "初始楼层的ID"
},
"hero": {
"_type": "object",
"_data": {
"image": {
"_leaf": true,
"_type": "select",
"_select": {
"values": [null].concat(Object.keys(editor.core.material.images.images).filter(function (name) {
return name.endsWith('.png');
}))
},
"_data": "行走图"
},
"animate": {
"_leaf": true,
"_type": "checkbox",
"_docs": "帧动画",
"_data": "是否开启停止状态和对话框的帧动画"
},
"name": {
"_leaf": true,
"_type": "textarea",
"_string": true,
"_data": "勇士名"
},
"lv": {
"_leaf": true,
"_type": "textarea",
"_range": "thiseval==~~thiseval &&thiseval>0",
"_data": "初始等级"
},
"hpmax": {
"_leaf": true,
"_type": "textarea",
"_data": "生命上限"
},
"hp": {
"_leaf": true,
"_type": "textarea",
"_data": "初始生命"
},
"manamax": {
"_leaf": true,
"_type": "textarea",
"_docs": "魔力上限",
"_data": "魔力上限此项非负才会生效null或小于0都不会生效"
},
"mana": {
"_leaf": true,
"_type": "textarea",
"_data": "初始魔力"
},
"atk": {
"_leaf": true,
"_type": "textarea",
"_data": "初始攻击"
},
"def": {
"_leaf": true,
"_type": "textarea",
"_data": "初始防御"
},
"mdef": {
"_leaf": true,
"_type": "textarea",
"_data": "初始护盾"
},
"money": {
"_leaf": true,
"_type": "textarea",
"_data": "初始金币"
},
"exp": {
"_leaf": true,
"_type": "textarea",
"_data": "初始经验"
},
"equipment": {
"_leaf": true,
"_type": "textarea",
"_hide": true,
"_range": "thiseval instanceof Array",
"_data": "初始装备"
},
"items": {
"_type": "object",
"_hide": true,
"_data": {
"constants": {
"_leaf": true,
"_type": "textarea",
"_range": "thiseval instanceof Object && !(thiseval instanceof Array)",
"_docs": "永久道具",
"_data": "初始永久道具个数,例如初始送手册可以写 {\"book\": 1}"
},
"tools": {
"_leaf": true,
"_type": "textarea",
"_range": "thiseval instanceof Object && !(thiseval instanceof Array)",
"_docs": "消耗道具",
"_data": "初始消耗道具个数,例如初始有两破可以写 {\"pickaxe\": 2}"
},
"equips": {
"_leaf": true,
"_type": "textarea",
"_range": "thiseval instanceof Object && !(thiseval instanceof Array)",
"_docs": "初始拥有装备个数",
"_data": "初始装备个数,例如初始送铁剑可以写 {\"sword1\": 1}"
}
}
},
"loc": {
"_type": "object",
"_data": {
"direction": {
"_leaf": true,
"_type": "select",
"_data": "初始朝向",
"_select": {
"values": [
"up",
"down",
"left",
"right"
]
},
},
"x": {
"_leaf": true,
"_type": "textarea",
"_data": "横坐标"
},
"y": {
"_leaf": true,
"_type": "textarea",
"_data": "纵坐标"
}
}
},
"flags": {
"_leaf": true,
"_type": "textarea",
"_range": "thiseval instanceof Object && !(thiseval instanceof Array)",
"_data": "游戏变量"
},
"followers": {
"_leaf": true,
"_type": "disable",
"_hide": true,
"_data": "跟随者"
},
"steps": {
"_leaf": true,
"_type": "disable",
"_hide": true,
"_data": "行走步数"
}
}
},
"startCanvas": {
"_leaf": true,
"_type": "event",
"_event": "firstArrive",
"_range": "thiseval==null || thiseval instanceof Array",
"_docs": "标题事件",
"_data": "标题界面事件化,可以使用事件流的形式来绘制开始界面等。\n需要开启startUsingCanvas这个开关。\n详见文档-个性化-标题界面事件化。"
},
"startText": {
"_leaf": true,
"_type": "event",
"_event": "firstArrive",
"_range": "thiseval==null || thiseval instanceof Array",
"_docs": "开场剧情",
"_data": "游戏开始前剧情,可以执行任意自定义事件。\n双击进入事件编辑器。\n如果无剧情直接留一个空数组即可。"
},
"shops": {
"_leaf": true,
"_type": "event",
"_event": "shop",
"_range": "thiseval instanceof Array",
"_docs": "全局商店",
"_data": "全局商店,是一个数组,可以双击进入事件编辑器。"
},
"levelUp": {
"_leaf": true,
"_type": "event",
"_event": "level",
"_range": "thiseval==null || thiseval instanceof Array",
"_docs": "等级提升",
"_data": "经验升级所需要的数值,是一个数组,可以双击进行编辑。 \n 第一项为初始等级仅title生效 \n 每一个里面可以含有三个参数 need, title, action \n need为所需要的经验数值可以是个表达式。请确保need依次递增 \n title为该等级的名称也可以省略代表使用系统默认值本项将显示在状态栏中 \n action为本次升级所执行的事件可由若干项组成"
}
}
},
"values": {
"_type": "object",
"_data": {
"lavaDamage": {
"_leaf": true,
"_type": "textarea",
"_data": "血网伤害"
},
"poisonDamage": {
"_leaf": true,
"_type": "textarea",
"_data": "中毒伤害"
},
"weakValue": {
"_leaf": true,
"_type": "textarea",
"_docs": "衰弱效果",
"_data": "衰弱状态下攻防减少的数值\n如果此项不小于1则作为实际下降的数值比如10就是攻防各下降10\n如果在0到1之间则为下降的比例比如0.3就是下降30%的攻防)"
},
"redGem": {
"_leaf": true,
"_type": "textarea",
"_docs": "红宝石值",
},
"blueGem": {
"_leaf": true,
"_type": "textarea",
"_docs": "蓝宝石值",
},
"greenGem": {
"_leaf": true,
"_type": "textarea",
"_docs": "绿宝石值",
},
"redPotion": {
"_leaf": true,
"_type": "textarea",
"_docs": "红血瓶值",
},
"bluePotion": {
"_leaf": true,
"_type": "textarea",
"_docs": "蓝血瓶值",
},
"yellowPotion": {
"_leaf": true,
"_type": "textarea",
"_docs": "黄血瓶值",
},
"greenPotion": {
"_leaf": true,
"_type": "textarea",
"_docs": "绿血瓶值",
},
"breakArmor": {
"_leaf": true,
"_type": "textarea",
"_docs": "破甲比例",
"_data": "破甲的比例战斗前怪物附加角色防御的x倍作为伤害可以用怪物的 defValue 覆盖此值。"
},
"counterAttack": {
"_leaf": true,
"_type": "textarea",
"_docs": "反击比例",
"_data": "反击的比例战斗时怪物每回合附加角色攻击的x倍作为伤害无视角色防御可以用怪物的 atkValue 覆盖此值。"
},
"purify": {
"_leaf": true,
"_type": "textarea",
"_docs": "净化比例",
"_data": "净化的比例战斗前怪物附加勇士护盾的x倍作为伤害可以用怪物的 n 覆盖此值。"
},
"hatred": {
"_leaf": true,
"_type": "textarea",
"_docs": "仇恨增值",
"_data": "仇恨属性中,每杀死一个怪物获得的仇恨值"
},
"animateSpeed": {
"_leaf": true,
"_type": "textarea",
"_docs": "全局帧动画时间",
"_data": "全局帧动画时间即怪物振动频率一般300比较合适"
},
"moveSpeed": {
"_leaf": true,
"_type": "textarea",
"_docs": "勇士移速",
"_data": "勇士每一格的移速默认是100此项可被用户修改覆盖"
},
"statusCanvasRowsOnMobile": {
"_leaf": true,
"_type": "select",
"_select": {
"values": [1, 2, 3, 4, 5]
},
"_docs": "竖状态栏自绘行数",
"_data": "竖屏模式下顶端状态栏canvas化后的行数。\n此项将决定竖屏的状态栏高度如果设置则不小于1且不大于5。\n仅在statusCanvas开启时才有效"
},
"floorChangeTime": {
"_leaf": true,
"_type": "textarea",
"_docs": "楼层切换时间",
"_data": "默认楼层切换时间;当楼层切换没有显式设置时间时将用此值;可以被用户在系统设置内手动修改"
}
}
},
"flags": {
"_type": "object",
"_data": {
"statusBarItems": {
"_leaf": true,
"_type": "checkboxSet",
"_checkboxSet": {
"prefix": [
"楼层",
"名字",
"<br>等级",
"血限",
"<br>生命",
"魔力",
"<br>攻击",
"防御",
"<br>护盾",
"金币",
"<br>经验",
"升级",
"<br>升级扣除模式",
"<br>钥匙",
"绿钥",
"<br>破炸",
"负面",
"<br>技能"
],
"key": [
"enableFloor",
"enableName",
"enableLv",
"enableHPMax",
"enableHP",
"enableMana",
"enableAtk",
"enableDef",
"enableMDef",
"enableMoney",
"enableExp",
"enableLevelUp",
"levelUpLeftMode",
"enableKeys",
"enableGreenKey",
"enablePZF",
"enableDebuff",
"enableSkill"
]
},
"_data": "状态栏显示项"
},
"autoScale": {
"_leaf": true,
"_type": "checkbox",
"_docs": "自动缩放最大化",
"_data": "是否自动缩放最大化,关闭后不再最大化"
},
"extendToolbar": {
"_leaf": true,
"_type": "checkbox",
"_docs": "横屏隐藏状态栏",
"_data": "在横屏状态下是否隐藏左侧状态栏从而获得仿RM的沉浸式体验"
},
"flyNearStair": {
"_leaf": true,
"_type": "checkbox",
"_docs": "楼传需在楼梯边",
"_data": "传送器是否需要在楼梯边使用如果flyRecordPosition开启则此项对箭头也有效。"
},
"flyRecordPosition": {
"_leaf": true,
"_type": "checkbox",
"_docs": "楼传开平面模式",
"_data": "传送器平面塔模式;此模式下楼层传送器将飞到上次离开该楼层的位置。"
},
"itemFirstText": {
"_leaf": true,
"_type": "checkbox",
"_docs": "首次道具进行提示",
"_data": "首次获得道具是否提示"
},
"equipboxButton": {
"_leaf": true,
"_type": "checkbox",
"_docs": "状态栏装备按钮",
"_data": "状态栏的装备按钮。若此项为true则将状态栏中的楼层转换器按钮换为装备栏按钮"
},
"enableAddPoint": {
"_leaf": true,
"_type": "checkbox",
"_docs": "开启加点",
"_data": "是否支持加点"
},
"enableNegativeDamage": {
"_leaf": true,
"_type": "checkbox",
"_docs": "开启负伤",
"_data": "是否支持负伤害(回血)"
},
"betweenAttackMax": {
"_leaf": true,
"_type": "checkbox",
"_docs": "夹击不超伤害值",
"_data": "夹击伤害是否不超过怪物伤害值。"
},
"useLoop": {
"_leaf": true,
"_type": "checkbox",
"_docs": "二分临界",
"_data": "是否循环计算临界如果此项为true则使用循环法而不是回合数计算法来算临界\n从V2.5.3开始,对于大数据的循环法将改为使用二分法进行计算"
},
"startUsingCanvas": {
"_leaf": true,
"_type": "checkbox",
"_docs": "标题开启事件化",
"_data": "是否开始菜单canvas化如果此项为true则将使用canvas来绘制开始菜单"
},
"statusCanvas": {
"_leaf": true,
"_type": "checkbox",
"_docs": "开启自绘状态栏",
"_data": "是否状态栏canvas化即手动自定义绘制状态栏。\n如果此项开启则可在脚本编辑的drawStatusBar中自定义绘制菜单栏。"
},
"enableEnemyPoint": {
"_leaf": true,
"_type": "checkbox",
"_docs": "定点怪显",
"_data": "是否开启怪物的定点显示功能,即属性不同的怪物会在怪物手册单列;用户可以手动在菜单栏中开关"
},
"enableGentleClick": {
"_leaf": true,
"_type": "checkbox",
"_docs": "允许轻按",
"_data": "是否允许轻触(获得面前物品)"
},
"ignoreChangeFloor": {
"_leaf": true,
"_type": "checkbox",
"_docs": "允许穿透楼梯",
"_data": "经过楼梯、传送门时是否能“穿透”。\n穿透的意思是自动寻路得到的的路径中间经过了楼梯行走时是否触发楼层转换事件"
},
"canGoDeadZone": {
"_leaf": true,
"_type": "checkbox",
"_docs": "允许将死领域",
"_data": "是否允许走到将死的领域上。如果此项为true则可以走到将死的领域上"
},
"enableMoveDirectly": {
"_leaf": true,
"_type": "checkbox",
"_docs": "允许瞬移",
"_data": "是否允许瞬间移动"
},
"enableRouteFolding": {
"_leaf": true,
"_type": "checkbox",
"_docs": "录像折叠",
"_data": "是否开启录像折叠功能。\n此功能将尽可能的通过优化无损耗反复走的方式来缩短录像但在某些情况下尤其是创新向塔中可能会存在副作用影响录像的正确性。"
},
"disableShopOnDamage": {
"_leaf": true,
"_type": "checkbox",
"_docs": "伤害禁用商店",
"_data": "是否在经过领域/夹击/路障等伤害后禁用快捷商店。"
},
"blurFg": {
"_leaf": true,
"_type": "checkbox",
"_docs": "虚化前景层",
"_data": "是否虚化前景层;如果此项开启,则在游戏中事件层有东西(如宝石等)时虚化前景层。"
}
}
}
}
}

View File

@ -0,0 +1,39 @@
/*
* 表格配置项
* 在这里可以对表格中的各项显示进行配置包括表格项提示内容等内容具体写法照葫芦画瓢即可
* 本配置项包括公共事件
* 相关文档 _docs/editor.md ~ http://127.0.0.1:1055/_docs/#/editor?id=修改表格
*/
var events_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
"_type": "object",
"_data": {
"commonEvent": {
"_type": "object",
"_data": function (key) {
var obj = {
"加点事件": {
"_leaf": true,
"_type": "event",
"_range": "thiseval instanceof Array",
"_event": "commonEvent",
"_data": "加点事件"
},
"回收钥匙商店": {
"_leaf": true,
"_type": "event",
"_event": "commonEvent",
"_data": "回收钥匙商店"
},
}
if (obj[key]) return obj[key];
return {
"_leaf": true,
"_type": "event",
"_event": "commonEvent",
"_data": "公共事件"
}
}
}
}
}

View File

@ -0,0 +1,213 @@
/*
* 表格配置项
* 在这里可以对表格中的各项显示进行配置包括表格项提示内容等内容具体写法照葫芦画瓢即可
* 本配置项包括脚本编辑
* 相关文档 _docs/editor.md ~ http://127.0.0.1:1055/_docs/#/editor?id=修改表格
*/
var functions_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
"_type": "object",
"_data": {
"events": {
"_type": "object",
"_data": {
"resetGame": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "重置游戏"
},
"win": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "游戏获胜"
},
"lose": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "游戏失败"
},
"changingFloor": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "切换楼层中"
},
"afterChangeFloor": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "切换楼层后"
},
"flyTo": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "楼层飞行"
},
"beforeBattle": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "战前判定"
},
"afterBattle": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "战后脚本"
},
"afterOpenDoor": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "开门后脚本"
},
"afterGetItem": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "道具后脚本"
},
"afterPushBox": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "推箱子后"
}
}
},
"enemys": {
"_type": "object",
"_data": {
"getSpecials": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "怪物特殊属性"
},
"getEnemyInfo": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "怪物真实属性"
},
"getDamageInfo": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "战斗伤害信息"
}
}
},
"actions": {
"_type": "object",
"_data": {
"onKeyUp": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "按键处理"
},
"onStatusBarClick": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_docs": "点击状态栏",
"_data": "状态栏点击事件,仅在开启自绘状态栏时生效"
}
}
},
"control": {
"_type": "object",
"_data": {
"saveData": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "存档操作"
},
"loadData": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "读档操作"
},
"getStatusLabel": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "状态名定义"
},
"triggerDebuff": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "毒衰咒处理"
},
"updateStatusBar": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "更新状态栏"
},
"updateCheckBlock": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "阻激夹域伤害"
},
"moveOneStep": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "每步后操作"
},
"moveDirectly": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "瞬间移动"
},
"parallelDo": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "并行脚本"
}
}
},
"ui": {
"_type": "object",
"_data": {
"getToolboxItems": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "道具栏显示项"
},
"drawStatusBar": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_preview": "statusBar",
"_data": "自绘状态栏"
},
"drawStatistics": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "数据统计"
},
"drawAbout": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "关于界面"
}
}
}
}
}

View File

@ -0,0 +1,88 @@
/*
* 表格配置项
* 在这里可以对表格中的各项显示进行配置包括表格项提示内容等内容具体写法照葫芦画瓢即可
* 本配置项包括插件编写
* 相关文档 _docs/editor.md ~ http://127.0.0.1:1055/_docs/#/editor?id=修改表格
*/
var plugins_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
"_type": "object",
"_data": function (key) {
var obj = {
"init": {
"_leaf": true,
"_type": "textarea",
"_range": "typeof(thiseval)=='string'",
"_data": "初始化"
},
"shop": {
"_leaf": true,
"_type": "textarea",
"_range": "typeof(thiseval)=='string'",
"_data": "全局商店"
},
"drawLight": {
"_leaf": true,
"_type": "textarea",
"_range": "typeof(thiseval)=='string' || thiseval==null",
"_data": "灯光效果"
},
"removeMap": {
"_leaf": true,
"_type": "textarea",
"_range": "typeof(thiseval)=='string' || thiseval==null",
"_data": "砍层插件"
},
"fiveLayers": {
"_leaf": true,
"_type": "textarea",
"_range": "typeof(thiseval)=='string' || thiseval==null",
"_data": "五图层(背景前景2)"
},
"itemShop": {
"_leaf": true,
"_type": "textarea",
"_range": "typeof(thiseval)=='string' || thiseval==null",
"_data": "道具商店"
},
"enemyLevel": {
"_leaf": true,
"_type": "textarea",
"_range": "typeof(thiseval)=='string' || thiseval==null",
"_data": "手册显示怪物境界"
},
"multiHeros": {
"_leaf": true,
"_type": "textarea",
"_range": "typeof(thiseval)=='string' || thiseval==null",
"_data": "多角色"
},
"heroFourFrames": {
"_leaf": true,
"_type": "textarea",
"_range": "typeof(thiseval)=='string' || thiseval==null",
"_data": "勇士四帧行走动画"
},
"routeFixing": {
"_leaf": true,
"_type": "textarea",
"_range": "typeof(thiseval)=='string' || thiseval==null",
"_data": "录像精修"
},
"numpad": {
"_leaf": true,
"_type": "textarea",
"_range": "typeof(thiseval)=='string' || thiseval==null",
"_data": "整数输入面板美化"
}
}
if (obj[key]) return obj[key];
return {
"_leaf": true,
"_type": "textarea",
"_range": "typeof(thiseval)=='string' || thiseval==null",
"_template": "function () {\\n\\t// 在此增加新插件\\n\\t\\n}",
"_data": "自定义插件"
}
}
}

60
_server/thirdparty/LICENSE.md vendored Normal file
View File

@ -0,0 +1,60 @@
/* jsColor */
The MIT License (MIT)
Copyright (c) 2014 Peter Dematté
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
/* awesomplete */
The MIT License (MIT)
Copyright (c) 2015 Lea Verou
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
/* caret-position */
The MIT License (MIT)
Copyright (c) 2015 Jonathan Ong me@jongleberry.com
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

75
_server/thirdparty/awesomplete.css vendored Normal file
View File

@ -0,0 +1,75 @@
.awesomplete [hidden] {
display: none;
}
.awesomplete .visually-hidden {
position: absolute;
clip: rect(0, 0, 0, 0);
}
.awesomplete {
display: inline-block;
position: relative;
}
.awesomplete > input {
display: block;
}
.awesomplete > ul {
position: absolute;
left: 0;
z-index: 1;
box-sizing: border-box;
list-style: none;
padding: 0;
margin: 0;
white-space: nowrap;
}
.awesomplete > ul:empty {
display: none;
}
.awesomplete > ul {
border-radius: .3em;
margin: .8em 0 0;
text-shadow: none;
}
@supports (transform: scale(0)) {
.awesomplete > ul {
transition: .3s cubic-bezier(.4,.2,.5,1.4);
transform-origin: 1.43em -.43em;
}
.awesomplete > ul[hidden],
.awesomplete > ul:empty {
opacity: 0;
transform: scale(0);
display: block;
transition-timing-function: ease;
}
}
/* Pointer */
.awesomplete > ul:before {
content: "";
position: absolute;
top: -.43em;
left: 1em;
width: 0; height: 0;
padding: .4em;
border: inherit;
border-right: 0;
border-bottom: 0;
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
.awesomplete > ul > li {
position: relative;
padding: .2em .5em;
cursor: pointer;
word-break: keep-all;
}

2
_server/thirdparty/awesomplete.min.js vendored Normal file

File diff suppressed because one or more lines are too long

158
_server/thirdparty/caret-position.js vendored Normal file
View File

@ -0,0 +1,158 @@
/* jshint browser: true */
(function () {
// We'll copy the properties below into the mirror div.
// Note that some browsers, such as Firefox, do not concatenate properties
// into their shorthand (e.g. padding-top, padding-bottom etc. -> padding),
// so we have to list every single property explicitly.
var properties = [
'direction', // RTL support
'boxSizing',
'width', // on Chrome and IE, exclude the scrollbar, so the mirror div wraps exactly as the textarea does
'height',
'overflowX',
'overflowY', // copy the scrollbar for IE
'borderTopWidth',
'borderRightWidth',
'borderBottomWidth',
'borderLeftWidth',
'borderStyle',
'paddingTop',
'paddingRight',
'paddingBottom',
'paddingLeft',
// https://developer.mozilla.org/en-US/docs/Web/CSS/font
'fontStyle',
'fontVariant',
'fontWeight',
'fontStretch',
'fontSize',
'fontSizeAdjust',
'lineHeight',
'fontFamily',
'textAlign',
'textTransform',
'textIndent',
'textDecoration', // might not make a difference, but better be safe
'letterSpacing',
'wordSpacing',
'tabSize',
'MozTabSize'
];
var isBrowser = (typeof window !== 'undefined');
var isFirefox = (isBrowser && window.mozInnerScreenX != null);
function getCaretCoordinates(element, position, options) {
if (!isBrowser) {
throw new Error('textarea-caret-position#getCaretCoordinates should only be called in a browser');
}
var debug = options && options.debug || false;
if (debug) {
var el = document.querySelector('#input-textarea-caret-position-mirror-div');
if (el) el.parentNode.removeChild(el);
}
// The mirror div will replicate the textarea's style
var div = document.createElement('div');
div.id = 'input-textarea-caret-position-mirror-div';
document.body.appendChild(div);
var style = div.style;
var computed = window.getComputedStyle ? window.getComputedStyle(element) : element.currentStyle; // currentStyle for IE < 9
var isInput = element.nodeName === 'INPUT';
// Default textarea styles
style.whiteSpace = 'nowrap';
style.zIndex = 2000;
if (!isInput)
style.wordWrap = 'break-word'; // only for textarea-s
// Position off-screen
style.position = 'absolute'; // required to return coordinates properly
if (!debug)
style.visibility = 'hidden'; // not 'display: none' because we want rendering
// Transfer the element's properties to the div
properties.forEach(function (prop) {
if (isInput && prop === 'lineHeight') {
// Special case for <input>s because text is rendered centered and line height may be != height
if (computed.boxSizing === "border-box") {
var height = parseInt(computed.height);
var outerHeight =
parseInt(computed.paddingTop) +
parseInt(computed.paddingBottom) +
parseInt(computed.borderTopWidth) +
parseInt(computed.borderBottomWidth);
var targetHeight = outerHeight + parseInt(computed.lineHeight);
if (height > targetHeight) {
style.lineHeight = height - outerHeight + "px";
} else if (height === targetHeight) {
style.lineHeight = computed.lineHeight;
} else {
style.lineHeight = 0;
}
} else {
style.lineHeight = computed.height;
}
} else {
style[prop] = computed[prop];
}
});
if (!isInput)
style.whiteSpace = 'pre-wrap';
if (isFirefox) {
// Firefox lies about the overflow property for textareas: https://bugzilla.mozilla.org/show_bug.cgi?id=984275
if (element.scrollHeight > parseInt(computed.height))
style.overflowY = 'scroll';
} else {
style.overflow = 'hidden'; // for Chrome to not render a scrollbar; IE keeps overflowY = 'scroll'
}
div.textContent = element.value.substring(0, position);
// The second special handling for input type="text" vs textarea:
// spaces need to be replaced with non-breaking spaces - http://stackoverflow.com/a/13402035/1269037
if (isInput)
div.textContent = div.textContent.replace(/\s/g, '\u00a0');
var span = document.createElement('span');
// Wrapping must be replicated *exactly*, including when a long word gets
// onto the next line, with whitespace at the end of the line before (#7).
// The *only* reliable way to do that is to copy the *entire* rest of the
// textarea's content into the <span> created at the caret position.
// For inputs, just '.' would be enough, but no need to bother.
span.textContent = element.value.substring(position) || '.'; // || because a completely empty faux span doesn't render at all
div.appendChild(span);
var coordinates = {
top: span.offsetTop + parseInt(computed['borderTopWidth']),
left: span.offsetLeft + parseInt(computed['borderLeftWidth']),
height: parseInt(computed['lineHeight'])
};
if (debug) {
span.style.backgroundColor = '#aaa';
} else {
document.body.removeChild(div);
}
return coordinates;
}
if (typeof module != 'undefined' && typeof module.exports != 'undefined') {
module.exports = getCaretCoordinates;
} else if(isBrowser) {
window.getCaretCoordinates = getCaretCoordinates;
}
}());

4
_server/thirdparty/color.all.min.js vendored Normal file

File diff suppressed because one or more lines are too long

305
_server/thirdparty/jsColor.js vendored Normal file
View File

@ -0,0 +1,305 @@
// ------ ColorPicker ------ //
(function (window) {
window.jsColorPicker = function(selectors, config) {
var renderCallback = function(colors, mode) {
var options = this,
input = options.input,
patch = options.patch,
RGB = colors.RND.rgb,
HSL = colors.RND.hsl,
AHEX = options.isIE8 ? (colors.alpha < 0.16 ? '0' : '') +
(Math.round(colors.alpha * 100)).toString(16).toUpperCase() + colors.HEX : '',
RGBInnerText = RGB.r + ',' + RGB.g + ',' + RGB.b,
RGBAText = RGBInnerText + ',' + colors.alpha,
isAlpha = colors.alpha !== 1 && !options.isIE8,
colorMode = input.getAttribute('data-colorMode');
patch.style.cssText =
'color:' + (colors.rgbaMixCustom.luminance > 0.22 ? '#222' : '#ddd') + ';' + // Black...???
'background-color: rgba(' + RGBAText + ');' +
'filter:' + (options.isIE8 ? 'progid:DXImageTransform.Microsoft.gradient(' + // IE<9
'startColorstr=#' + AHEX + ',' + 'endColorstr=#' + AHEX + ')' : '');
input.value = RGBAText;
if (options.displayCallback) {
options.displayCallback(colors, mode, options);
}
},
extractValue = function(elm) {
var val = elm.value || elm.getAttribute('value') || elm.style.backgroundColor || "0,0,0,1";
if (/^[0-9 ]+,[0-9 ]+,[0-9 ]+,[0-9. ]+$/.test(val)) return "rgba("+val+")";
if (/^[0-9 ]+,[0-9 ]+,[0-9 ]+$/.test(val)) return "rgba("+val+",1)";
return null;
},
actionCallback = function(event, action) {
var options = this,
colorPicker = colorPickers.current;
if (action === 'toMemory') {
var memos = colorPicker.nodes.memos,
backgroundColor = '',
opacity = 0,
cookieTXT = [];
for (var n = 0, m = memos.length; n < m; n++) {
backgroundColor = memos[n].style.backgroundColor;
opacity = memos[n].style.opacity;
opacity = Math.round((opacity === '' ? 1 : opacity) * 100) / 100;
cookieTXT.push(backgroundColor.
replace(/, /g, ',').
replace('rgb(', 'rgba(').
replace(')', ',' + opacity + ')')
);
}
cookieTXT = '\'' + cookieTXT.join('\',\'') + '\'';
ColorPicker.docCookies('colorPickerMemos' + (options.noAlpha ? 'NoAlpha' : ''), cookieTXT);
} else if (action === 'resizeApp') {
ColorPicker.docCookies('colorPickerSize', colorPicker.color.options.currentSize);
} else if (action === 'modeChange') {
var mode = colorPicker.color.options.mode;
ColorPicker.docCookies('colorPickerMode', mode.type + '-' + mode.z);
}
},
createInstance = function(elm, config) {
var initConfig = {
klass: window.ColorPicker,
input: elm,
patch: elm,
isIE8: !!document.all && !document.addEventListener, // Opera???
// *** animationSpeed: 200,
// *** draggable: true,
margin: {left: -1, top: 2},
customBG: '#FFFFFF',
// displayCallback: displayCallback,
/* --- regular colorPicker options from this point --- */
color: extractValue(elm),
initStyle: 'display: none',
mode: ColorPicker.docCookies('colorPickerMode') || 'hsv-h',
// memoryColors: (function(colors, config) {
// return config.noAlpha ?
// colors.replace(/\,\d*\.*\d*\)/g, ',1)') : colors;
// })($.docCookies('colorPickerMemos'), config || {}),
memoryColors: ColorPicker.docCookies('colorPickerMemos' +
((config || {}).noAlpha ? 'NoAlpha' : '')),
size: ColorPicker.docCookies('colorPickerSize') || 1,
renderCallback: renderCallback,
actionCallback: actionCallback
};
for (var n in config) {
initConfig[n] = config[n];
}
return new initConfig.klass(initConfig);
},
doEventListeners = function(elm, multiple, off) {
var onOff = off ? 'removeEventListener' : 'addEventListener',
inputListener = function(e) {
var index = multiple ? Array.prototype.indexOf.call(elms, this) : 0,
colorPicker = colorPickers[index] ||
(colorPickers[index] = createInstance(this, config)),
options = colorPicker.color.options;
options.color = extractValue(elm); // brings color to default on reset
//检查颜色合法性
if (options.color != null && options.color == options.color.match(/rgba\([0-9 ]+,[0-9 ]+,[0-9 ]+,[0-9. ]+\)/)[0]) {
var chec = options.color.match(/[0-9.]+/g);
if (chec.length != 4)
return;
for (var i = 0; i < 3; i++) {
if (chec[i] != chec[i].match(/\d+/)[0] || +chec[i] < 0 || +chec[i] > 255)
return;
}
if (chec[3] != chec[3].match(/\d+(\.\d+)?/)[0] || parseFloat(chec[3]) > 1 || parseFloat(chec[3] < 0))
return;
if (!multiple) {
colorPicker.setColor(extractValue(elm), undefined, undefined, true);
colorPicker.saveAsBackground();
}
colorPickers.current = colorPickers[index];
}
},
createListener = function() {
elm = document.getElementById("colorPicker");
var input = elm,
position = window.ColorPicker.getOrigin(input),
index = multiple ? Array.prototype.indexOf.call(elms, elm) : 0,
colorPicker = colorPickers[index] ||
(colorPickers[index] = createInstance(elm, config)),
options = colorPicker.color.options,
colorPickerUI = colorPicker.nodes.colorPicker,
appendTo = (options.appendTo || document.body),
isStatic = /static/.test(window.getComputedStyle(appendTo).position),
atrect = isStatic ? {left: 0, top: 0} : appendTo.getBoundingClientRect(),
waitTimer = 0;
options.color = extractValue(elm); // brings color to default on reset
colorPickerUI.style.cssText =
'position: absolute;' + (!colorPickers[index].cssIsReady ? 'display: none;' : '') +
'left:' + (position.left + options.margin.left - atrect.left) + 'px;' +
'top:' + (position.top + +input.offsetHeight + options.margin.top - atrect.top) + 'px;';
if (!multiple) {
options.input = elm;
options.patch = elm; // check again???
colorPicker.setColor(extractValue(elm), undefined, undefined, true);
colorPicker.saveAsBackground();
}
colorPickers.current = colorPickers[index];
appendTo.appendChild(colorPickerUI);
waitTimer = setInterval(function() { // compensating late style on onload in colorPicker
if (colorPickers.current.cssIsReady) {
waitTimer = clearInterval(waitTimer);
colorPickerUI.style.display = 'block';
}
}, 10);
},
hideListener = function(e) {
var colorPicker = colorPickers.current,
colorPickerUI = (colorPicker ? colorPicker.nodes.colorPicker : undefined),
animationSpeed = colorPicker ? colorPicker.color.options.animationSpeed : 0,
isColorPicker = colorPicker && (function(elm) {
while (elm) {
if ((elm.className || '').indexOf('cpPanel') !== -1) return elm;
elm = elm.parentNode;
}
return false;
})(e.target),
inputIndex = Array.prototype.indexOf.call(elms, e.target);
if (isColorPicker && Array.prototype.indexOf.call(colorPickers, isColorPicker)) {
if (e.target === colorPicker.nodes.exit) {
colorPickerUI.parentNode.style.display = 'none';
document.activeElement.blur();
} else {
// ...
}
} else if (inputIndex !== -1) {
// ...
} else if (colorPickerUI) {
colorPickerUI.parentNode.style.display = 'none';
}
};
elm[onOff]('input', inputListener);
window.jsColorPicker.create = createListener;
},
// this is a way to prevent data binding on HTMLElements
colorPickers = window.jsColorPicker.colorPickers || [],
elms = document.querySelectorAll(selectors),
testColors = new window.Colors({customBG: config.customBG, allMixDetails: true});
window.jsColorPicker.colorPickers = colorPickers;
for (var n = 0, m = elms.length; n < m; n++) {
var elm = elms[n];
if (config === 'destroy') {
doEventListeners(elm, (config && config.multipleInstances), true);
if (colorPickers[n]) {
colorPickers[n].destroyAll();
}
} else {
var color = extractValue(elm);
var value = color.split('(');
testColors.setColor(color);
if (config && config.init) {
config.init(elm, testColors.colors);
}
elm.setAttribute('data-colorMode', value[1] ? value[0].substr(0, 3) : 'HEX');
doEventListeners(elm, (config && config.multipleInstances), false);
if (config && config.readOnly) {
elm.readOnly = true;
}
}
};
return window.jsColorPicker.colorPickers;
};
window.ColorPicker.docCookies = function(key, val, options) {
var encode = encodeURIComponent, decode = decodeURIComponent,
cookies, n, tmp, cache = {},
days;
if (val === undefined) { // all about reading cookies
cookies = document.cookie.split(/;\s*/) || [];
for (n = cookies.length; n--; ) {
tmp = cookies[n].split('=');
if (tmp[0]) cache[decode(tmp.shift())] = decode(tmp.join('=')); // there might be '='s in the value...
}
if (!key) return cache; // return Json for easy access to all cookies
else return cache[key]; // easy access to cookies from here
} else { // write/delete cookie
options = options || {};
if (val === '' || options.expires < 0) { // prepare deleteing the cookie
options.expires = -1;
// options.path = options.domain = options.secure = undefined; // to make shure the cookie gets deleted...
}
if (options.expires !== undefined) { // prepare date if any
days = new Date();
days.setDate(days.getDate() + options.expires);
}
document.cookie = encode(key) + '=' + encode(val) +
(days ? '; expires=' + days.toUTCString() : '') +
(options.path ? '; path=' + options.path : '') +
(options.domain ? '; domain=' + options.domain : '') +
(options.secure ? '; secure' : '');
}
};
})(this);
// Added
jsColorPicker('input.color', {
customBG: '#222',
readOnly: false,
// patch: false,
init: function(elm, colors) { // colors is a different instance (not connected to colorPicker)
elm.style.backgroundColor = elm.value;
elm.style.color = colors.rgbaMixCustom.luminance > 0.22 ? '#222' : '#ddd';
},
appendTo: document.getElementById("colorPanel"),
size: 1,
});
function openColorPicker(px, py, callback) {
window.jsColorPicker.confirm = callback;
var colorPanel = document.getElementById('colorPanel');
if (colorPanel.style.display=='none' && px != null && py != null) {
colorPanel.style.display = "inline-block";
colorPanel.style.left = px + 'px';
colorPanel.style.top = py + 'px';
window.jsColorPicker.create();
}
else {
colorPanel.style.display = 'none';
delete window.jsColorPicker.confirm;
}
}
function confirmColor() {
var colorPicker = document.getElementById("colorPicker");
if (window.jsColorPicker.confirm) { /* 存在块 */
// 检测需要是合法数值
var val = colorPicker.value;
if (/^[0-9 ]+,[0-9 ]+,[0-9 ]+,[0-9. ]+$/.test(val)) val = "rgba("+val+")";
else if (/^[0-9 ]+,[0-9 ]+,[0-9 ]+$/.test(val)) val = "rgba("+val+",1)";
else val = null;
if (val) window.jsColorPicker.confirm(val);
}
else {
colorPicker.select();
document.execCommand("Copy");
}
colorPanel.style.display = 'none';
delete window.jsColorPicker.confirm;
}
// ------ AutoCompletion ------

495
editor-mobile.html Normal file
View File

@ -0,0 +1,495 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,minimum-scale=1,maximum-scale=1,initial-scale=1,user-scalable=no" />
<link href="_server/css/editor_mobile.css" rel="stylesheet">
<link href="_server/CodeMirror/codemirror.css" rel="stylesheet">
<link href="_server/thirdparty/awesomplete.css" rel="stylesheet">
<link id="color_css" rel="stylesheet">
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>
<script>
if(innerWidth>innerHeight){ //pic:1242*2208 | chrome info:1340*2380
confirm('宽大于高的设备请使用正常版本的editor, 点击确定跳转')?(window.location='./editor.html'):'';
}
if (location.protocol.indexOf("http")!=0) {
alert("请在启动服务中打开本编辑器!不然包括编辑在内的绝大多数功能都无法使用。");
}
</script>
<div class="main">
<div id="left" style="z-index:-1;opacity: 0;"><!-- map -->
<div id="arrEditor">
<table class="col" id='arrColMark'></table>
<table class="row" id='arrRowMark'></table>
<div id="mapEditArea">
<textarea cols="10" rows="10" id="pout"></textarea>
</div>
<div id="editTip">
<input id='newFileName' placeholder="新楼层id" style="width: 100px"/>
<span style="vertical-align: bottom"></span>
<input id='newMapWidth' style="width: 20px"/>
<span style="vertical-align: bottom"></span>
<input id='newMapHeight' style="width: 20px"/>
<input type="checkbox" id='newMapStatus' checked='checked' style='vertical-align: bottom'/>
<span style='vertical-align: bottom;'>保留楼层属性</span>
<br/>
<input type="button" value="新建空白地图" id='newMap'/>
</div>
<div id='editBtns'>
<input type="button" value="导出并复制地图" id="exportMap"/>
<input type="button" value="导入地图" id="importMap"/>
<input type="button" value="清除地图" id='clearMapButton'/>
<input type="button" value="删除地图" id="deleteMap"/>
</div>
<input type="button" value="批量创建空白地图 ↓" id='newMaps'/>
<div id='newFloors' style='display:none'>
<span style="vertical-align: bottom">楼层ID格式: </span>
<input id='newFloorIds' style="width: 70px" value='MT${i}'/>
<br/>
<span style="vertical-align: bottom">地图中文名格式: </span>
<input id='newFloorTitles' style="width: 100px" value='主塔 ${i} 层'/>
<br/>
<span style="vertical-align: bottom">状态栏名称: </span>
<input id='newFloorNames' style="width: 70px" value='${i}'/>
<br/>
<span style="vertical-align: bottom"></span>
<input id='newMapsWidth' style="width: 20px"/>
<span style="vertical-align: bottom"></span>
<input id='newMapsHeight' style="width: 20px"/>
<input type="checkbox" id='newMapsStatus' checked='checked' style='vertical-align: bottom'/>
<span style='vertical-align: bottom; margin-left: -4px'>保留楼层属性</span>
<br/>
<span style="vertical-align: bottom">从 i=</span>
<input id='newMapsFrom' value="1" style="width: 20px"/>
<span style="vertical-align: bottom"></span>
<input id='newMapsTo' value="5" style="width: 20px"/>
<input type="button" value="确认创建" id='createNewMaps'>
</div>
</div>
</div>
<div id="left1" class='leftTab' style="z-index:-1;opacity: 0;"><!-- appendpic -->
<h3 class="leftTabHeader">追加素材</h3>
<div class="leftTabContent">
<p>
<input id="selectFileBtn" type="button" value="导入文件到画板"/>
<select id="selectAppend"></select>
<!-- ["terrains", "animates", "enemys", "enemy48", "items", "npcs", "npc48"] -->
<input id="appendConfirm" type="button" value="追加"/>
<input id="quickAppendConfirm" type="button" value="快速追加"/>
<span style="font-size: 13px">自动注册</span><input id="appendRegister" type="checkbox" checked/>
</p>
<p>
色相:<input id='changeColorInput' type="range" min="0" max="12" step="1" value="0" list="huelists" style="width: 60%;margin-left: 3%;vertical-align: middle">
<datalist id="huelists" style="display: none">
<option value="0"/><option value="1"/><option value="2"/>
<option value="3"/><option value="4"/><option value="5"/>
<option value="6"/><option value="7"/><option value="8"/>
<option value="9"/><option value="10"/><option value="11"/><option value="12"/>
</datalist>
</p>
<div id="appendPicCanvas" style="position:relative;overflow: auto;height:470px;">
<canvas style="position:absolute"></canvas><!-- 用于画出灰白相间背景 -->
<canvas style="position:absolute"></canvas><!-- 用于画出选中文件 -->
<canvas style="position:absolute;z-index:100"></canvas><!-- 用于响应鼠标点击 -->
<canvas style="position:absolute;display:none;"></canvas><!-- 画出追加后的sprite用于储存 -->
<div id="appendPicSelection">
<div class="appendSelection"><span style="top: 0; left: 2px;">1</span></div>
<div class="appendSelection"><span style="top: 0; left: 14px;">2</span></div>
<div class="appendSelection"><span style="top: 12px; left: 2px;">3</span></div>
<div class="appendSelection"><span style="top: 12px; left: 14px;">4</span></div>
</div>
</div>
</div>
</div>
<div id="left2" class='leftTab' style="z-index:-1;opacity: 0;"><!-- loc -->
<h3 class="leftTabHeader">地图选点&nbsp;&nbsp;<button onclick="editor.mode.onmode('save')">保存</button>&nbsp;&nbsp;<button onclick="editor.uifunctions.addAutoEvent()">添加自动事件页</button>&nbsp;&nbsp;<button onclick="editor_multi.editCommentJs('loc')">配置表格</button>
</h3>
<div class="leftTabContent">
<p id='pos_a6771a78_a099_417c_828f_0a24851ebfce' style="margin-left: 15px">0,0</p>
<div class='etable'>
<table>
<tbody id='table_3d846fc4_7644_44d1_aa04_433d266a73df'>
<tr>
<td>条目</td>
<td>注释</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="left3" class='leftTab' style="z-index:-1;opacity: 0;"><!-- enemyitem -->
<h3 class="leftTabHeader">图块属性&nbsp;&nbsp;<button onclick="editor.mode.onmode('save')">保存</button>&nbsp;&nbsp;<button onclick="editor.mode.changeDoubleClickModeByButton('add')">添加</button>&nbsp;&nbsp;<button onclick="editor.mode.changeDoubleClickModeByButton('delete')">删除</button>&nbsp;&nbsp;<button onclick="editor_multi.editCommentJs('enemyitem')">配置表格</button>
</h3>
<div class="leftTabContent">
<div id="enemyItemTable"><!-- enemy and item -->
<div class='etable'>
<table>
<tbody id='table_a3f03d4c_55b8_4ef6_b362_b345783acd72'>
<tr>
<td>条目</td>
<td>注释</td>
<td></td>
</tr>
</tbody>
</table>
</div>
<div style="margin-top: -10px; margin-bottom: 10px">
<button id="copyEnemyItem">复制属性</button>
<button id="pasteEnemyItem">粘贴属性</button>
<button id="clearEnemyItem">清空属性</button>
<button id="clearAllEnemyItem">批量清空属性</button>
</div>
</div>
<div id='newIdIdnum'><!-- id and idnum -->
<input placeholder="新id唯一标识符"/>
<input placeholder="新idnum10000以内数字"/>
<button>确定</button>
<br/>
<button style="margin-top: 10px">自动注册</button>
<button style="margin-top: 10px; margin-left: 5px">删除此素材</button>
<button style="margin-top: 10px; margin-left: 5px">以此素材为模板追加</button>
</div>
<div id='changeId'><!-- id and idnum -->
<input placeholder="修改图块id为" style="width: 100px"/>
<button>确定</button>
<button style="margin-left: 5px">删除此素材</button>
<button style="margin-left: 5px">以此素材为模板追加</button>
</div>
</div>
</div>
<div id="left4" class='leftTab' style="z-index:-1;opacity: 0;"><!-- floor -->
<h3 class="leftTabHeader">楼层属性&nbsp;&nbsp;<button onclick="editor.mode.onmode('save')">保存</button>&nbsp;&nbsp;<button onclick="editor.mode.changeDoubleClickModeByButton('add')">添加</button>&nbsp;&nbsp;<button onclick="editor.mode.changeDoubleClickModeByButton('delete')">删除</button>&nbsp;&nbsp;<button onclick="editor_multi.editCommentJs('floor')">配置表格</button>
</h3>
<div class="leftTabContent">
<div class='etable'>
<table>
<tbody id='table_4a3b1b09_b2fb_4bdf_b9ab_9f4cdac14c74'>
<tr>
<td>条目</td>
<td>注释</td>
<td></td>
</tr>
</tbody>
</table>
</div>
<div id='changeFloorId'><!-- id and idnum -->
<input placeholder="修改floorId为"/>
<button>确定</button>
</div>
<div id='changeFloorSize' style="font-size: 13px;">
修改地图大小:宽<input style="width: 25px;" value="13" />,高<input style="width: 25px;" value="13" />
偏移x<input style="width: 25px;" value="0" /> y<input style="width: 25px;" value="0" />
<button>确定</button>
</div>
</div>
</div>
<div id="left5" class='leftTab' style="z-index:-1;opacity: 0;"><!-- tower -->
<h3 class="leftTabHeader">全塔属性&nbsp;&nbsp;<button onclick="editor.mode.onmode('save')">保存</button>&nbsp;&nbsp;<button onclick="editor.mode.changeDoubleClickModeByButton('add')">添加</button>&nbsp;&nbsp;<button onclick="editor_multi.editCommentJs('tower')">配置表格</button>
</h3>
<div class="leftTabContent">
<div class='etable'>
<table>
<tbody id='table_b6a03e4c_5968_4633_ac40_0dfdd2c9cde5'>
<tr>
<td>条目</td>
<td>注释</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="left6" class='leftTab' style="z-index:-1;opacity: 0;">
<div style="position: relative; height: 95%"><!-- eventsEditor -->
<h3>事件编辑器 &nbsp;&nbsp;
<!--
<button onclick="editor_blockly.showXML()">Show XML</button>
<button onclick="editor_blockly.runCode()">console.log(obj=code)</button>
-->
<button onclick="editor_blockly.confirm()">确认</button>
<button onclick="editor_blockly.confirm(true)">应用</button>
<button id='blocklyParse' onclick="editor_blockly.parse()">解析</button>
<button onclick="editor_blockly.cancel()">取消</button>
<!-- 手机端放不下,因此不显示搜索框 -->
<div style="display: none">
<div class="searchLogo"></div>
<input type="text" id="searchBlock" placeholder="搜索事件块..."/>
</div>
<button class="cpPanel" onclick="editor_blockly.selectPointFromButton()">地图选点</button>
<button class="cpPanel" onclick="editor.uievent.searchUsedFlags()" style="margin-left:5px">变量出现位置搜索</button>
<input type="checkbox" class="cpPanel" id="blocklyReplace" onchange="editor_blockly.triggerReplace()" style="margin-left: 10px" />
<span class="cpPanel" style="margin-left: -4px; font-size: 13px">开启中文名替换</span>
<input type="checkbox" class="cpPanel" id="blocklyExpandCompare" onchange="editor_blockly.triggerExpandCompare()" style="margin-left: 10px" />
<span class="cpPanel" style="margin-left: -4px; font-size: 13px">展开值块逻辑运算</span>
<xml id="toolbox" style="display:none">
</xml>
</h3>
<div style="position: relative;height: 100%">
<div id="blocklyArea">
<div id="blocklyDiv"></div>
</div>
<textarea id="codeArea" spellcheck="false"></textarea>
</div>
</div>
</div>
<div id="colorPanel" class="cpPanel" style="display: none">
<input class="color" id="colorPicker" value="255,215,0,1"/>
<button onclick="confirmColor()">确定</button>
</div>
<div id="left7" style="z-index:-1;opacity: 0;"><!-- 多行文本编辑器 -->
<button onclick="editor_multi.confirm()">确认</button>
<button onclick="editor_multi.cancel()">取消</button>
<button onclick="editor_multi.confirm(true)">应用</button>
<button onclick="editor_multi.format()">格式化</button>
<button id="editor_multi_preview" style="display: none;">预览</button>
<input type="checkbox" onclick="editor_multi.toggerLint()" id="lintCheckbox"
style="vertical-align: middle;margin-left:6px"/>
<span style="vertical-align: middle; margin-left: -3px">语法检查</span>
<select id="codemirrorCommands" onchange="editor_multi.doCommand(this)" style="vertical-align: middle; margin-left: 6px;"></select>
<textarea id="multiLineCode" name="multiLineCode"></textarea>
</div>
<div id="left8" class='leftTab' style="z-index:-1;opacity: 0;"><!-- functions -->
<h3 class="leftTabHeader">脚本编辑&nbsp;&nbsp;<button onclick="editor.mode.onmode('save')">保存</button>&nbsp;&nbsp;<button onclick="editor_multi.editCommentJs('functions')">配置表格</button>
</h3>
<div class="leftTabContent">
<div class='etable'>
<table>
<tbody id='table_e260a2be_5690_476a_b04e_dacddede78b3'>
<tr>
<td>条目</td>
<td>注释</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="left9" class='leftTab' style="z-index:-1;opacity: 0;"><!-- commonevent -->
<h3 class="leftTabHeader">公共事件&nbsp;&nbsp;<button onclick="editor.mode.onmode('save')">保存</button>&nbsp;&nbsp;<button onclick="editor.table.addfunc()">添加</button>&nbsp;&nbsp;<button onclick="editor.mode.changeDoubleClickModeByButton('delete')">删除</button>&nbsp;&nbsp;<button onclick="editor_multi.editCommentJs('commonevent')">配置表格</button>
</h3>
<div class="leftTabContent">
<div class='etable'>
<table>
<tbody id='table_b7bf0124_99fd_4af8_ae2f_0017f04a7c7d'>
<tr>
<td>条目</td>
<td>注释</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="left10" class='leftTab' style="z-index:-1;opacity: 0;"><!-- plugins -->
<h3 class="leftTabHeader">插件编写&nbsp;&nbsp;<button onclick="editor.mode.onmode('save')">保存</button>&nbsp;&nbsp;<button onclick="editor.table.addfunc()">添加</button>&nbsp;&nbsp;<button onclick="editor.mode.changeDoubleClickModeByButton('delete')">删除</button>&nbsp;&nbsp;<button onclick="editor_multi.editCommentJs('plugins')">配置表格</button>
</h3>
<div class="leftTabContent">
<div class='etable'>
<table>
<tbody id='table_e2c034ec_47c6_48ae_8db8_4f8f32fea2d6'>
<tr>
<td>条目</td>
<td>注释</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="mid">
<div class="col" id='mapColMark'></div>
<div class="row" id='mapRowMark'></div>
<div class="map" id="mapEdit">
<canvas class='gameCanvas' id='ebm'></canvas>
<canvas class='gameCanvas' id='efg'></canvas>
<canvas class='gameCanvas' id='eui' style='z-index:100'></canvas>
</div>
</div>
<div id="mid2" style="display: none">
<p style="margin: 10px"><span id='lastUsedTitle'></span> <button id='clearLastUsedBtn'>清除</button></p>
<div class="map" style="height: 160px; margin-top: 25px" id="lastUsedDiv">
<canvas class='gameCanvas' id='lastUsed'></canvas>
</div>
</div>
<div id="right" style="z-index:-1;opacity: 0;">
<div id="iconLib">
<div id="iconImages"></div>
<div id="selectBox">
<div id='dataSelection' style="display:none"></div>
</div>
</div>
<button id="iconExpandBtn"></button>
</div>
<div id="down">
<div style="margin:0.5rem">
<div class="tools">
<div id="tip"></div>
<span id='mobileview'>
<input type="button" value="数据区"/>
<input type="button" value="地图区"/>
<br />
<input type="button" value="素材库"/>
<input type="button" value="前往游戏" onclick="window.location='./index.html'"/>
</span>
<div id="menuDiv">
<div id="midMenu" style="display:none">
<div id='extraEvent' class='menuitem' style="display:none"><div class="menuitem-content"></div></div>
<div id='chooseThis' class="menuitem"><div class="menuitem-content">选中此点</div></div>
<div id='chooseInRight' class="menuitem"><div class="menuitem-content">在素材区选中此图块</div></div>
<div id='copyLoc' class="menuitem"><div class="menuitem-content">复制此事件</div></div>
<div id='pasteLoc' class="menuitem"><div class="menuitem-content">粘贴到此事件</div></div>
<div id='clearEvent' class="menuitem"><div class="menuitem-content">仅清空此点事件</div></div>
<div id='clearLoc' class="menuitem"><div class="menuitem-content">清空此点及事件</div></div>
</div>
</div>
<select id="editModeSelect" style="font-size: 12px">
<option value="map">地图编辑</option>
<option value="loc">地图选点</option>
<option value="enemyitem">图块属性</option>
<option value="floor">楼层属性</option>
<option value="tower">全塔属性</option>
<option value="functions">脚本编辑</option>
<option value="appendpic">追加素材</option>
<option value="commonevent">公共事件</option>
<option value="plugins">插件编写</option>
</select>
<span style="font-size: 12px"><input type="checkbox" id="showMovable"/>通行度</span>
<select id="editorTheme" style="font-size: 11px;">
<option value="editor_color">默认白</option>
<option value="editor_color_dark">夜间黑</option>
</select>
<select id="brushMod" style="clear:right">
<option value="line">画线</option>
<option value="rectangle">画矩形</option>
<option value="tileset">tile平铺</option>
<option value="fill">填充模式</option>
</select>
<select id="layerMod" style="float:left;margin-right:3px">
<option value="bgmap">背景层</option>
<option value="map" selected>事件层</option>
<option value="fgmap">前景层</option>
</select>
<div id="viewportButtons" style="float:left">
<input type="button" style="padding:1px 1px" value="←"/>
<input type="button" style="padding:1px 6px" value="↑"/>
<input type="button" style="padding:1px 6px" value="↓"/>
<input type="button" style="padding:1px 1px" value="→"/>
<input type="button" id="bigmapBtn" value="大地图" style="margin-left: 5px"/>
</div>
<select id="selectFloor" style="clear:left"></select>
<input type="button" value="选层" id='selectFloorBtn'/>
<input type="button" value="保存地图" id='saveFloor'/>
<input type="button" value="后退" id="undoFloor" style="display: none;"/>
<input type="button" value="帮助文档" id="openDoc" />
<span id='mobileeditdata' style="display:none">
<input type="button" value="编辑"/>
<input type="button" value="显示完整名称" style="display: none;"/>
<input type="button" value="显示完整注释"/>
</span>
</div>
</div>
</div>
</div>
<!-- <script>/* -->
<div id="gameInject" style='display: none'></div>
<!-- UI预览 & 地图选点 -->
<div id='uieventDiv' style='display: none'>
<div id='uieventDialog'>
<div id="uieventHead">
<span id="uieventTitle"></span>
<select id="uieventSelect" style="margin-left: 20px"></select>
<button id="uieventNo">关闭</button>
<button id="uieventYes">确定</button>
</div>
<hr style="clear: both; margin-top: 0"/>
<div id='uieventBody'>
<canvas class='gameCanvas' id='uievent'></canvas>
<div id="selectPointBox"></div>
<div id="uieventExtraBody" style="display: none"></div>
</div>
<div id="selectPoint">
<select id="selectPointFloor"></select>
<div id="selectPointButtons">
<input type="button" value="←"/>
<input type="button" value="↑"/>
<input type="button" value="↓"/>
<input type="button" value="→"/>
<input type="button" value="大地图" style="margin-left: 5px"/>
<input type="button" value="复制楼层ID">
</div>
</div>
</div>
</div>
<!-- */</script> -->
<!-- =========================================================== -->
<!-- <script src='_server/vendor/vue.min.js'></script> -->
<!-- <script src="https://cdn.bootcss.com/vue/2.5.13/vue.js"></script> -->
<!-- <script src='_server/vendor/polyfill.min.js'></script> -->
<script src='_server/fs.js'></script>
<script src='_server/editor_config.js'></script>
<script src='_server/editor_util.js'></script>
<script src='_server/editor_game.js'></script>
<script src='_server/editor_file.js'></script>
<script src='_server/editor_table.js'></script>
<script src='_server/editor_mode.js'></script>
<script src='_server/editor_ui.js'></script>
<script src='_server/editor_uievent.js'></script>
<script src='_server/editor_mappanel.js'></script>
<script src='_server/editor_datapanel.js'></script>
<script src='_server/editor_materialpanel.js'></script>
<script src='_server/editor_listen.js'></script>
<script src='libs/thirdparty/lz-string.min.js'></script>
<script src='libs/thirdparty/localforage.min.js'></script>
<script src='libs/thirdparty/zip.min.js'></script>
<script src='_server/editor.js'></script>
<script>
editor.isMobile=true;
editor.init(function () {
editor.listen();
editor.mode_listen();
editor.mobile_listen();
});
//main.listen();
</script>
<!-- hightlight textarea -->
<script src='_server/editor_multi.js'></script>
<!-- blockly -->
<script src="_server/blockly/Converter.bundle.min.js"></script>
<script src="_server/blockly/blockly_compressed.js"></script>
<script src="_server/blockly/blocks_compressed.js"></script>
<script src="_server/blockly/javascript_compressed.js"></script>
<script src="_server/blockly/zh-hans.js"></script>
<script src='_server/MotaActionParser.js'></script>
<script src='_server/editor_blocklyconfig.js'></script>
<script src='_server/editor_blockly.js'></script>
<!-- codemirror -->
<script src="_server/CodeMirror/codeMirror.bundle.min.js"></script>
<script src="_server/CodeMirror/beautify.min.js"></script>
<script src="_server/CodeMirror/jshint.min.js"></script>
<script src="_server/CodeMirror/codeMirror.plugin.min.js"></script>
<script src="_server/CodeMirror/acorn.min.js"></script>
<script src="_server/CodeMirror/defs.js"></script>
<script src="_server/CodeMirror/tern.min.js"></script>
<!-- thirdparty -->
<script src="_server/thirdparty/color.all.min.js"></script>
<script src="_server/thirdparty/awesomplete.min.js"></script>
<script src="_server/thirdparty/caret-position.js"></script>
<script src="_server/thirdparty/jsColor.js"></script>
</body>
</html>

479
editor.html Normal file
View File

@ -0,0 +1,479 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<link href="_server/css/editor.css" rel="stylesheet">
<link href="_server/CodeMirror/codemirror.css" rel="stylesheet">
<link href="_server/thirdparty/awesomplete.css" rel="stylesheet">
<link id="color_css" rel="stylesheet">
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
</head>
<body>
<script>
if(innerWidth<innerHeight){ //pic:1242*2208 | chrome info:1340*2380
confirm('高大于宽的设备请使用移动版本的editor, 点击确定跳转')?(window.location='./editor-mobile.html'):'';
}
if (location.protocol.indexOf("http")!=0) {
alert("请在启动服务中打开本编辑器!不然包括编辑在内的绝大多数功能都无法使用。");
}
</script>
<div class="main">
<div id="left" style="z-index:-1;opacity: 0;"><!-- map -->
<div id="arrEditor">
<table class="col" id='arrColMark'></table>
<table class="row" id='arrRowMark'></table>
<div id="mapEditArea">
<textarea cols="10" rows="10" id="pout"></textarea>
</div>
<div id="editTip">
<input type="button" value="新建空白地图" id='newMap'/>
<input id='newFileName' placeholder="新楼层id" style="width: 70px"/>
<span style="vertical-align: bottom"></span>
<input id='newMapWidth' style="width: 20px"/>
<span style="vertical-align: bottom"></span>
<input id='newMapHeight' style="width: 20px"/>
<input type="checkbox" id='newMapStatus' checked='checked' style='vertical-align: bottom'/>
<span style='vertical-align: bottom; margin-left: -4px'>保留楼层属性</span>
</div>
<div id="editBtns">
<input type="button" value="导出并复制地图" id="exportMap"/>
<input type="button" value="从框中导入地图" id="importMap"/>
<input type="button" value="清除地图" id='clearMapButton'/>
<input type="button" value="删除地图" id="deleteMap"/>
</div>
<input type="button" value="批量创建空白地图 ↓" id='newMaps'/>
<div id='newFloors' style='display:none'>
<span style="vertical-align: bottom">楼层ID格式: </span>
<input id='newFloorIds' style="width: 70px" value='MT${i}'/>
<span style="vertical-align: bottom">地图中文名格式: </span>
<input id='newFloorTitles' style="width: 100px" value='主塔 ${i} 层'/>
<br/>
<span style="vertical-align: bottom">状态栏名称: </span>
<input id='newFloorNames' style="width: 70px" value='${i}'/>
<span style="vertical-align: bottom"></span>
<input id='newMapsWidth' style="width: 20px"/>
<span style="vertical-align: bottom"></span>
<input id='newMapsHeight' style="width: 20px"/>
<input type="checkbox" id='newMapsStatus' checked='checked' style='vertical-align: bottom'/>
<span style='vertical-align: bottom; margin-left: -4px'>保留楼层属性</span>
<br/>
<span style="vertical-align: bottom">从 i=</span>
<input id='newMapsFrom' value="1" style="width: 20px"/>
<span style="vertical-align: bottom"></span>
<input id='newMapsTo' value="5" style="width: 20px"/>
<input type="button" value="确认创建" id='createNewMaps'>
</div>
</div>
</div>
<div id="left1" class='leftTab' style="z-index:-1;opacity: 0;"><!-- appendpic -->
<h3 class="leftTabHeader">追加素材</h3>
<div class="leftTabContent">
<p>
<input id="selectFileBtn" type="button" value="导入文件到画板"/>
<select id="selectAppend"></select>
<!-- ["terrains", "animates", "enemys", "enemy48", "items", "npcs", "npc48"] -->
<input id="appendConfirm" type="button" value="追加"/>
<input id="quickAppendConfirm" type="button" value="快速追加"/>
<span style="font-size: 13px">&nbsp;&nbsp;自动注册</span><input id="appendRegister" type="checkbox" checked/>
</p>
<p><small>从V2.7.1开始你可以直接将素材图片拖到对应的素材区将自动追加并注册。同时4x4的道具素材已支持快速追加一次16个。</small></p>
<p>
色相:<input id='changeColorInput' type="range" min="0" max="12" step="1" value="0" list="huelists" style="width: 60%;margin-left: 3%;vertical-align: middle">
<datalist id="huelists" style="display: none">
<option value="0"/><option value="1"/><option value="2"/>
<option value="3"/><option value="4"/><option value="5"/>
<option value="6"/><option value="7"/><option value="8"/>
<option value="9"/><option value="10"/><option value="11"/><option value="12"/>
</datalist>
</p>
<div id="appendPicCanvas" style="position:relative;overflow: auto;height:470px;">
<canvas style="position:absolute"></canvas><!-- 用于画出灰白相间背景 -->
<canvas style="position:absolute"></canvas><!-- 用于画出选中文件 -->
<canvas style="position:absolute;z-index:100"></canvas><!-- 用于响应鼠标点击 -->
<canvas style="position:absolute;display:none;"></canvas><!-- 画出追加后的sprite用于储存 -->
<div id="appendPicSelection">
<div class="appendSelection"><span style="top: 0; left: 2px;">1</span></div>
<div class="appendSelection"><span style="top: 0; left: 14px;">2</span></div>
<div class="appendSelection"><span style="top: 12px; left: 2px;">3</span></div>
<div class="appendSelection"><span style="top: 12px; left: 14px;">4</span></div>
</div>
</div>
</div>
</div>
<div id="left2" class='leftTab' style="z-index:-1;opacity: 0;"><!-- loc -->
<h3 class="leftTabHeader">地图选点&nbsp;&nbsp;<button onclick="editor.mode.onmode('save')">保存</button>&nbsp;&nbsp;<button onclick="editor.uifunctions.addAutoEvent()">添加自动事件页</button>&nbsp;&nbsp;<button onclick="editor_multi.editCommentJs('loc')">配置表格</button>
</h3>
<div class="leftTabContent">
<p id='pos_a6771a78_a099_417c_828f_0a24851ebfce' style="margin-left: 15px">0,0</p>
<div class='etable'>
<table>
<tbody id='table_3d846fc4_7644_44d1_aa04_433d266a73df'>
<tr>
<td>条目</td>
<td>注释</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="left3" class='leftTab' style="z-index:-1;opacity: 0;"><!-- enemyitem -->
<h3 class="leftTabHeader">图块属性&nbsp;&nbsp;<button onclick="editor.mode.onmode('save')">保存</button>&nbsp;&nbsp;<button onclick="editor.mode.changeDoubleClickModeByButton('add')">添加</button>&nbsp;&nbsp;<button onclick="editor.mode.changeDoubleClickModeByButton('delete')">删除</button>&nbsp;&nbsp;<button onclick="editor_multi.editCommentJs('enemyitem')">配置表格</button>
</h3>
<div class="leftTabContent">
<div id="enemyItemTable"><!-- enemy and item -->
<div class='etable'>
<table>
<tbody id='table_a3f03d4c_55b8_4ef6_b362_b345783acd72'>
<tr>
<td>条目</td>
<td>注释</td>
<td></td>
</tr>
</tbody>
</table>
</div>
<div style="margin-top: -10px; margin-bottom: 10px">
<button id="copyEnemyItem">复制属性</button>
<button id="pasteEnemyItem">粘贴属性</button>
<button id="clearEnemyItem">清空属性</button>
<button id="clearAllEnemyItem">批量清空属性</button>
</div>
</div>
<div id='newIdIdnum'><!-- id and idnum -->
<input placeholder="新id唯一标识符"/>
<input placeholder="新idnum10000以内数字"/>
<button>确定</button>
<br/>
<button style="margin-top: 10px">自动注册</button>
<button style="margin-top: 10px; margin-left: 5px">删除此素材</button>
<button style="margin-top: 10px; margin-left: 5px">以此素材为模板追加</button>
</div>
<div id='changeId'><!-- id and idnum -->
<input placeholder="修改图块id为" style="width: 100px"/>
<button>确定</button>
<button style="margin-left: 5px">删除此素材</button>
<button style="margin-left: 5px">以此素材为模板追加</button>
</div>
</div>
</div>
<div id="left4" class='leftTab' style="z-index:-1;opacity: 0;"><!-- floor -->
<h3 class="leftTabHeader">楼层属性&nbsp;&nbsp;<button onclick="editor.mode.onmode('save')">保存</button>&nbsp;&nbsp;<button onclick="editor.mode.changeDoubleClickModeByButton('add')">添加</button>&nbsp;&nbsp;<button onclick="editor.mode.changeDoubleClickModeByButton('delete')">删除</button>&nbsp;&nbsp;<button onclick="editor_multi.editCommentJs('floor')">配置表格</button>
</h3>
<div class="leftTabContent">
<div class='etable'>
<table>
<tbody id='table_4a3b1b09_b2fb_4bdf_b9ab_9f4cdac14c74'>
<tr>
<td>条目</td>
<td>注释</td>
<td></td>
</tr>
</tbody>
</table>
</div>
<div id='changeFloorId'><!-- id and idnum -->
<input placeholder="修改floorId为"/>
<button>确定</button>
</div>
<div id='changeFloorSize' style="font-size: 13px;">
修改地图大小:宽<input style="width: 25px;" value="13" />,高<input style="width: 25px;" value="13" />
偏移x<input style="width: 25px;" value="0" /> y<input style="width: 25px;" value="0" />
<button>确定</button>
</div>
</div>
</div>
<div id="left5" class='leftTab' style="z-index:-1;opacity: 0;"><!-- tower -->
<h3 class="leftTabHeader">全塔属性&nbsp;&nbsp;<button onclick="editor.mode.onmode('save')">保存</button>&nbsp;&nbsp;<button onclick="editor.mode.changeDoubleClickModeByButton('add')">添加</button>&nbsp;&nbsp;<button onclick="editor_multi.editCommentJs('tower')">配置表格</button>
</h3>
<div class="leftTabContent">
<div class='etable'>
<table>
<tbody id='table_b6a03e4c_5968_4633_ac40_0dfdd2c9cde5'>
<tr>
<td>条目</td>
<td>注释</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="left6" class='leftTab' style="z-index:-1;opacity: 0;">
<div style="position: relative; height: 95%"><!-- eventsEditor -->
<h3>事件编辑器 &nbsp;&nbsp;
<!--
<button onclick="editor_blockly.showXML()">Show XML</button>
<button onclick="editor_blockly.runCode()">console.log(obj=code)</button>
-->
<button onclick="editor_blockly.confirm()">确认</button>
<button onclick="editor_blockly.confirm(true)">应用</button>
<button id='blocklyParse' onclick="editor_blockly.parse()">解析</button>
<button onclick="editor_blockly.cancel()">取消</button>
<div style="position: relative; display: inline-block; margin-left: 10px">
<div class="searchLogo"></div>
<input type="text" id="searchBlock" placeholder="搜索事件块..."/>
</div>
<button class="cpPanel" onclick="editor_blockly.selectPointFromButton()" style="margin-left:5px">地图选点</button>
<button class="cpPanel" onclick="editor.uievent.searchUsedFlags()" style="margin-left:5px">变量出现位置搜索</button>
<input type="checkbox" class="cpPanel" id="blocklyReplace" onchange="editor_blockly.triggerReplace()" style="margin-left: 10px" />
<span class="cpPanel" style="margin-left: -4px; font-size: 13px">开启中文名替换</span>
<input type="checkbox" class="cpPanel" id="blocklyExpandCompare" onchange="editor_blockly.triggerExpandCompare()" style="margin-left: 10px" />
<span class="cpPanel" style="margin-left: -4px; font-size: 13px">展开值块逻辑运算</span>
<xml id="toolbox" style="display:none">
</xml>
</h3>
<div style="position: relative;height: 100%">
<div id="blocklyArea">
<div id="blocklyDiv"></div>
</div>
<textarea id="codeArea" spellcheck="false"></textarea>
</div>
</div>
</div>
<div id="colorPanel" class="cpPanel" style="display: none">
<input class="color" id="colorPicker" value="255,215,0,1"/>
<button onclick="confirmColor()">确定</button>
</div>
<div id="left7" style="z-index:-1;opacity: 0;"><!-- 多行文本编辑器 -->
<button onclick="editor_multi.confirm()">确认</button>
<button onclick="editor_multi.cancel()">取消</button>
<button onclick="editor_multi.confirm(true)">应用</button>
<button onclick="editor_multi.format()">格式化</button>
<button id="editor_multi_preview" style="display: none;">预览</button>
<input type="checkbox" onclick="editor_multi.toggerLint()" id="lintCheckbox"
style="vertical-align: middle;margin-left:6px"/>
<span style="vertical-align: middle; margin-left: -3px">语法检查</span>
<select id="codemirrorCommands" onchange="editor_multi.doCommand(this)" style="vertical-align: middle; margin-left: 6px;"></select>
<textarea id="multiLineCode" name="multiLineCode"></textarea>
</div>
<div id="left8" class='leftTab' style="z-index:-1;opacity: 0;"><!-- functions -->
<h3 class="leftTabHeader">脚本编辑&nbsp;&nbsp;<button onclick="editor.mode.onmode('save')">保存</button>&nbsp;&nbsp;<button onclick="editor_multi.editCommentJs('functions')">配置表格</button>
</h3>
<div class="leftTabContent">
<div class='etable'>
<table>
<tbody id='table_e260a2be_5690_476a_b04e_dacddede78b3'>
<tr>
<td>条目</td>
<td>注释</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="left9" class='leftTab' style="z-index:-1;opacity: 0;"><!-- commonevent -->
<h3 class="leftTabHeader">公共事件&nbsp;&nbsp;<button onclick="editor.mode.onmode('save')">保存</button>&nbsp;&nbsp;<button onclick="editor.table.addfunc()">添加</button>&nbsp;&nbsp;<button onclick="editor.mode.changeDoubleClickModeByButton('delete')">删除</button>&nbsp;&nbsp;<button onclick="editor_multi.editCommentJs('commonevent')">配置表格</button>
</h3>
<div class="leftTabContent">
<div class='etable'>
<table>
<tbody id='table_b7bf0124_99fd_4af8_ae2f_0017f04a7c7d'>
<tr>
<td>条目</td>
<td>注释</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="left10" class='leftTab' style="z-index:-1;opacity: 0;"><!-- plugins -->
<h3 class="leftTabHeader">插件编写&nbsp;&nbsp;<button onclick="editor.mode.onmode('save')">保存</button>&nbsp;&nbsp;<button onclick="editor.table.addfunc()">添加</button>&nbsp;&nbsp;<button onclick="editor.mode.changeDoubleClickModeByButton('delete')">删除</button>&nbsp;&nbsp;<button onclick="editor_multi.editCommentJs('plugins')">配置表格</button>
</h3>
<div class="leftTabContent">
<div class='etable'>
<table>
<tbody id='table_e2c034ec_47c6_48ae_8db8_4f8f32fea2d6'>
<tr>
<td>条目</td>
<td>注释</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="mid">
<table class="col" id='mapColMark'></table>
<table class="row" id='mapRowMark'></table>
<div class="map" id="mapEdit">
<canvas class='gameCanvas' id='ebm'></canvas>
<canvas class='gameCanvas' id='efg'></canvas>
<canvas class='gameCanvas' id='eui' style='z-index:100'></canvas>
</div>
<div class="tools">
<div id="tip"></div>
<select id="editModeSelect" style="font-size: 12px">
<option value="map">地图编辑(Z)</option>
<option value="loc">地图选点(X)</option>
<option value="enemyitem">图块属性(C)</option>
<option value="floor">楼层属性(V)</option>
<option value="tower">全塔属性(B)</option>
<option value="functions">脚本编辑(N)</option>
<option value="appendpic">追加素材(M)</option>
<option value="commonevent">公共事件(,)</option>
<option value="plugins">插件编写(.)</option>
</select>
<span style="font-size: 12px"><input type="checkbox" id="showMovable" style="margin-left:0;margin-right: 2px"/>通行度</span>
<select id="editorTheme" style="margin-left: 0; font-size: 11px;">
<option value="editor_color">默认白</option>
<option value="editor_color_dark">夜间黑</option>
</select>
<br/>
<span style="font-size: 12px;">
<input type="radio" id="brushMod" name="brushMod" value="line" checked="checked" />线
<input type="radio" id="brushMod2" name="brushMod" value="rectangle" />矩形
<input type="radio" id="brushMod3" name="brushMod" value="tileset" />tile平铺
<input type="radio" id="brushMod4" name="brushMod" value="fill" />填充
</span>
<br/>
<span style="font-size: 12px">
<input type="radio" id="layerMod2" name="layerMod" value="bgmap" />背景层
<input type="radio" id="layerMod" name="layerMod" value="map" checked="checked" style="margin-left: 5px" />事件层
<input type="radio" id="layerMod3" name="layerMod" value="fgmap" style="margin-left: 5px" />前景层
</span>
<br>
<div id="viewportButtons" style="margin-bottom: 7px">
<input type="button" value="←"/>
<input type="button" value="↑"/>
<input type="button" value="↓"/>
<input type="button" value="→"/>
<input type="button" id='bigmapBtn' value="大地图" style="margin-left: 5px"/>
</div>
<select id="selectFloor" style="margin-bottom: 5px;"></select>
<input type="button" value="选层" id='selectFloorBtn'/>
<input type="button" value="保存地图" id='saveFloor'/>
<input type="button" value="后退" id="undoFloor" style="display: none;" />
<input type="button" value="帮助文档" id="openDoc" />
<input type="button" value="前往游戏" onclick="window.open('./index.html', '_blank')"/>
</div>
</div>
<div id="mid2">
<p style="margin: 10px"><span id='lastUsedTitle'></span><small>Ctrl+滚轮放缩,右键置顶)</small> <button id='clearLastUsedBtn'>清除</button></p>
<div class="map" id="lastUsedDiv">
<canvas id='lastUsed' class="gameCanvas" style="overflow: hidden"></canvas>
</div>
</div>
<div id="right">
<div id="iconLib">
<div id="iconImages"></div>
<div id="selectBox">
<div id='dataSelection' style="display:none"></div>
</div>
</div>
<button id="iconExpandBtn"></button>
</div>
<div id="menuDiv">
<div id="midMenu" style="display:none">
<div id='extraEvent' class='menuitem' style="display:none"><div class="menuitem-content"></div></div>
<div id='chooseThis' class="menuitem"><div class="menuitem-content">选中此点</div></div>
<div id='chooseInRight' class="menuitem"><div class="menuitem-content">在素材区选中此图块</div></div>
<div id='copyLoc' class="menuitem"><div class="menuitem-content">复制此事件</div></div>
<div id='pasteLoc' class="menuitem"><div class="menuitem-content">粘贴到此事件</div></div>
<div id='clearEvent' class="menuitem"><div class="menuitem-content">仅清空此点事件</div></div>
<div id='clearLoc' class="menuitem"><div class="menuitem-content">清空此点及事件</div></div>
</div>
</div>
</div>
<!-- <script>/* -->
<div id="gameInject" style='display: none'></div>
<!-- UI预览 & 地图选点 -->
<div id='uieventDiv' style='display: none'>
<div id='uieventDialog'>
<div id="uieventHead">
<span id="uieventTitle"></span>
<select id="uieventSelect" style="margin-left: 20px"></select>
<button id="uieventNo">关闭</button>
<button id="uieventYes">确定</button>
</div>
<hr style="clear: both; margin-top: 0"/>
<div id='uieventBody'>
<canvas class='gameCanvas' id='uievent'></canvas>
<div id="selectPointBox"></div>
<div id="uieventExtraBody" style="display: none; margin-top: -10px"></div>
</div>
<div id="selectPoint">
<select id="selectPointFloor"></select>
<div id="selectPointButtons">
<input type="button" value="←"/>
<input type="button" value="↑"/>
<input type="button" value="↓"/>
<input type="button" value="→"/>
<input type="button" value="切换大地图" style="margin-left: 10px;">
<input type="button" value="复制楼层ID">
</div>
</div>
</div>
</div>
<!-- */</script> -->
<!-- =========================================================== -->
<!-- <script src='_server/vendor/vue.min.js'></script> -->
<!-- <script src="https://cdn.bootcss.com/vue/2.5.13/vue.js"></script> -->
<!-- <script src='_server/vendor/polyfill.min.js'></script> -->
<script src='_server/fs.js'></script>
<script src='_server/editor_config.js'></script>
<script src='_server/editor_util.js'></script>
<script src='_server/editor_game.js'></script>
<script src='_server/editor_file.js'></script>
<script src='_server/editor_table.js'></script>
<script src='_server/editor_mode.js'></script>
<script src='_server/editor_ui.js'></script>
<script src='_server/editor_uievent.js'></script>
<script src='_server/editor_mappanel.js'></script>
<script src='_server/editor_datapanel.js'></script>
<script src='_server/editor_materialpanel.js'></script>
<script src='_server/editor_listen.js'></script>
<script src='libs/thirdparty/lz-string.min.js'></script>
<script src='libs/thirdparty/localforage.min.js'></script>
<script src='libs/thirdparty/zip.min.js'></script>
<script src='_server/editor.js'></script>
<script>
editor.init(function () {
editor.listen();
editor.mode_listen();
editor.mobile_listen();
});
//main.listen();
</script>
<!-- hightlight textarea -->
<script src='_server/editor_multi.js'></script>
<!-- blockly -->
<script src="_server/blockly/Converter.bundle.min.js"></script>
<script src="_server/blockly/blockly_compressed.js"></script>
<script src="_server/blockly/blocks_compressed.js"></script>
<script src="_server/blockly/javascript_compressed.js"></script>
<script src="_server/blockly/zh-hans.js"></script>
<script src='_server/MotaActionParser.js'></script>
<script src='_server/editor_blocklyconfig.js'></script>
<script src='_server/editor_blockly.js'></script>
<!-- codemirror -->
<script src="_server/CodeMirror/codeMirror.bundle.min.js"></script>
<script src="_server/CodeMirror/beautify.min.js"></script>
<script src="_server/CodeMirror/jshint.min.js"></script>
<script src="_server/CodeMirror/codeMirror.plugin.min.js"></script>
<script src="_server/CodeMirror/acorn.min.js"></script>
<script src="_server/CodeMirror/defs.js"></script>
<script src="_server/CodeMirror/tern.min.js"></script>
<!-- thirdparty -->
<script src="_server/thirdparty/color.all.min.js"></script>
<script src="_server/thirdparty/awesomplete.min.js"></script>
<script src="_server/thirdparty/caret-position.js"></script>
<script src="_server/thirdparty/jsColor.js"></script>
</body>
</html>

View File

@ -0,0 +1,514 @@
/**
* 运行时可编辑地图的扩展By fux2黄鸡
*/
"use strict";
function dynamicMapEditor() {
// 所有显示的ID
this.displayIds = [
'none', 'yellowWall', 'blueWall', 'whiteWall', 'yellowDoor', 'blueDoor', 'redDoor', 'star', 'lava', 'lavaNet',
'yellowKey', 'blueKey', 'redKey', 'redGem', 'blueGem', 'greenGem', 'yellowGem',
'redPotion', 'bluePotion', 'yellowPotion', 'greenPotion', 'pickaxe', 'bomb', 'centerFly',
'cls:autotile', 'cls:enemys', 'cls:enemy48'
];
this.items = [];
this.userChanged = [];
this.savedItems = [];
this.dom = null;
this.canvas = null;
this.mapRecord = {};
this.enemyModified = false;
this.valueModified = false;
this.pageId = 0;
this.pageMaxItems = 21;
this.pageMax = 0;
this.selectedIndex = 0;
this.selectedItem = null;
this._init();
}
// ------ init
dynamicMapEditor.prototype._init = function () {
this.dom = document.createElement("canvas");
this.dom.id = 'dynamicMapEditor';
this.dom.style.display = 'none';
this.dom.style.position = 'absolute';
this.dom.style.left = '3px';
this.dom.style.top = '3px';
this.dom.style.zIndex = 99999;
this.canvas = this.dom.getContext("2d");
core.dom.gameGroup.appendChild(this.dom);
this.initInfos();
this.pageMax = Math.ceil(this.items.length / this.pageMaxItems);
core.registerAction('onkeyUp', 'plugin_dme_keydown', this.onKeyUp.bind(this), 200);
core.registerAction('onclick', 'plugin_dme_click', this.onMapClick.bind(this), 200);
this.dom.addEventListener("click",this.onBoxClick.bind(this));
this.showInitHelp();
}
dynamicMapEditor.prototype.initInfos = function () {
this.items = [];
var ids = {};
this.displayIds.forEach(function (v) {
if (v.startsWith("cls:")) {
var cls = v.substr(4);
for (var id in core.maps.blocksInfo) {
var u = core.maps.blocksInfo[id];
if (u && u.cls == cls) {
if (ids[u.id]) continue;
this.items.push(core.getBlockInfo(u.id));
ids[u.id] = true;
}
}
} else if (v == 'none') {
this.items.push({"number": 0, "id": "none", "name": "清除块"});
} else {
this.items.push(core.getBlockInfo(v));
}
}, this);
this.items = this.items.filter(function (v) { return v && v.id && v.number >= 0; });
this.savedItems = core.getLocalStorage('_dynamicMapEditor_savedItems', []);
}
// ------ bind actions
dynamicMapEditor.prototype.isValid = function () {
return main.mode == 'play' && core.isPlaying() && !core.isReplaying() && !core.status.lockControl;
}
dynamicMapEditor.prototype.onKeyUp = function(e) {
if (!this.isValid()) return false;
if (e.keyCode == 219) {
this.openToolBox();
return true;
}
if (!this.isUsingTool) return false;
if (e.keyCode == 220) {
this.undo();
return true;
} else if (e.keyCode == 221) {
this.applyCurrentChange();
return true;
} else if (e.keyCode >= 48 && e.keyCode <= 57) {
// 0-9
if (e.altKey) {
this.savedItem(e.keyCode - 48);
} else {
this.loadItem(e.keyCode - 48);
}
return true;
}
return false;
}
dynamicMapEditor.prototype.onMapClick = function(x, y) {
if (!this.isValid()) return false;
if (!this.isUsingTool || !this.selectedItem) return false;
x += parseInt(core.bigmap.offsetX / 32);
y += parseInt(core.bigmap.offsetY / 32);
var number = this.selectedItem.number;
this.addOperation('put', number, x, y, core.status.floorId);
return true;
}
dynamicMapEditor.prototype.getClickLoc = function (e) {
return {
x: (e.clientX - core.dom.gameGroup.offsetLeft - 3) / core.domStyle.scale,
y: (e.clientY - core.dom.gameGroup.offsetTop - 3) / core.domStyle.scale,
};
}
dynamicMapEditor.prototype.onBoxClick = function (e) {
if (!this.isValid() || !this.isUsingTool) return false;
var loc = this.getClickLoc(e), x = loc.x, y = loc.y;
for(var i = 0; i < this.pageMaxItems; i++) {
var rect = this.itemRect(i);
if(x >= rect.x && x <= rect.x + rect.w && y >= rect.y && y <= rect.y + rect.h) {
this.onItemClick(i);
return;
}
}
if(y>=350 && y <= 370) {
if (x >= this.offsetX && x <= this.offsetX + 40) {
this.changePage(-1);
} else if (x >= this.offsetX + 40 && x <= this.offsetX + 80) {
this.showHelp(true);
} else if (x >= this.offsetX + 80 && x <= this.offsetX + 120) {
this.changePage(1);
}
}
}
dynamicMapEditor.prototype.onItemClick = function(index) {
var startIndex = this.pageId * this.pageMaxItems;
var item = this.items[startIndex + index];
if(!item) return;
if(index == this.selectedIndex) {
if (core.material.enemys[item.id]) {
var enemy = core.material.enemys[item.id];
var nowData = [enemy.hp, enemy.atk, enemy.def, enemy.special].join(';');
core.myprompt("请输入新怪物属性\n血;攻;防;能力,以分号分隔", nowData, function (result) {
if (result) {
try {
var finalData = result.split(';');
if (finalData.length < 4) throw "";
var hp = parseInt(finalData[0]) || 0;
var atk = parseInt(finalData[1]) || 0;
var def = parseInt(finalData[2]) || 0;
var special = finalData[3].replace(/[\[\]]/g, "")
.split(',').map(function (x) { return parseInt(x); });
if (special.length == 0) special = 0;
else if (special.length == 1) special = special[0];
dynamicMapEditor.addOperation('modify', item.id, hp, atk, def, special);
core.drawTip('已更新' + enemy.name + '的数据');
return;
} catch (e) {}
}
core.drawTip('无效的输入数据');
});
return;
}
if (core.values[item.id] != null) {
var nowData = core.values[item.id];
core.myprompt("请输入新" + (item.name || "") + "数值:", core.values[item.id], function (result) {
if (result) {
dynamicMapEditor.addOperation('value', item.id, parseInt(result) || 0, item.name || "");
core.drawTip('已更新' + (item.name || "") + "的数值");
return;
}
core.drawTip('无效的输入数据');
});
return;
}
} else {
this.selectedIndex = index;
this.selectedItem = item;
this.refreshToolBox();
}
}
// ------ methods
dynamicMapEditor.prototype.openToolBox = function() {
if (!this.isUsingTool && core.domStyle.isVertical) {
core.drawTip("竖屏模式下暂不支持此功能。");
return;
}
this.isUsingTool = !this.isUsingTool;
this.selectedItem = null;
this.selectedIndex = -1;
this.dom.style.display = this.isUsingTool ? 'block' : 'none';
this.dom.style.width = core.dom.statusCanvas.style.width;
this.dom.width = core.dom.statusCanvas.width / core.domStyle.ratio;
this.dom.style.height = core.dom.statusCanvas.style.height;
this.dom.height = core.dom.statusCanvas.height / core.domStyle.ratio;
this.offsetX = this.dom.width / 2 - 60;
this.refreshToolBox();
if (this.isUsingTool) this.showHelp();
}
dynamicMapEditor.prototype.addOperation = function() {
var operation = {};
var type = arguments[0];
operation.type = type;
if (type == 'put') {
operation.number = arguments[1];
operation.x = arguments[2];
operation.y = arguments[3];
operation.floorId = arguments[4];
operation.originNumber = core.floors[operation.floorId].map[operation.y][operation.x];
core.floors[operation.floorId].map[operation.y][operation.x] = operation.number;
core.setBlock(operation.number, operation.x, operation.y, operation.floorId);
this.mapRecord[operation.floorId] = true;
} else if (type == 'modify') {
operation.enemyId = arguments[1];
operation.hp = arguments[2];
operation.atk = arguments[3];
operation.def = arguments[4];
operation.special = arguments[5];
var enemy = core.material.enemys[operation.enemyId];
operation.originHp = enemy.hp;
operation.originAtk = enemy.atk;
operation.originDef = enemy.def;
operation.originSpecial = enemy.special;
enemy.hp = operation.hp;
enemy.atk = operation.atk;
enemy.def = operation.def;
enemy.special = operation.special;
this.enemyModified = true;
} else if (type == 'value') {
operation.id = arguments[1];
operation.value = arguments[2];
operation.name = arguments[3];
operation.originValue = core.values[operation.id];
core.values[operation.id] = operation.value;
this.valueModified = true;
}
this.userChanged.push(operation);
}
dynamicMapEditor.prototype.undo = function() {
var operation = this.userChanged.pop();
if(!operation) {
core.drawTip('没有动作可以撤销');
return;
}
var type = operation.type;
if(type == 'put') { // {originNumber, x, y, floorId}
var originNumber = operation.originNumber;
var x = operation.x;
var y = operation.y;
var floorId = operation.floorId;
core.floors[floorId].map[y][x] = originNumber;
core.setBlock(originNumber, x, y, floorId);
this.mapRecord[floorId] = true;
core.drawTip('已撤销' + floorId + '在(' + x + ',' + y + ')的图块操作');
} else if (type == 'modify') { // {enemyId, originHp, originAtk, originDef, originSpecial}
var enemyId = operation.enemyId;
var hp = operation.originHp;
var atk = operation.originAtk;
var def = operation.originDef;
var special = operation.originSpecial;
var enemy = core.material.enemys[enemyId];
enemy.hp = hp;
enemy.atk = atk;
enemy.def = def;
enemy.special = special;
core.drawTip('已撤销对' + enemy.name + '的属性修改');
this.enemyModified = true;
} else if (type == 'value') { // {id, value, originValue}
var id = operation.id;
var value = operation.originValue;
core.values[operation.id] = operation.originValue;
core.drawTip('已撤销对' + operation.name + "数值的修改");
this.valueModified = true;
}
}
dynamicMapEditor.prototype.changePage = function(delta) {
var newId = this.pageId + delta;
if (newId < 0 || newId >= this.pageMax) return;
this.pageId = newId;
this.selectedItem = null;
this.selectedIndex = -1;
this.refreshToolBox();
}
dynamicMapEditor.prototype.savedItem = function (number) {
if (!this.isUsingTool || this.selectedItem < 0) return;
this.savedItems[number] = [this.pageId, this.selectedIndex];
core.setLocalStorage('_dynamicMapEditor_savedItems', this.savedItems);
core.drawTip("已保存此图块");
}
dynamicMapEditor.prototype.loadItem = function (number) {
if (!this.isUsingTool) return;
var u = this.savedItems[number];
if (!u) return core.drawTip("没有保存的图块!");
this.pageId = u[0];
this.selectedIndex = u[1];
this.selectedItem = this.items[this.pageId * this.pageMaxItems + this.selectedIndex];
this.refreshToolBox();
}
// ------ draw
dynamicMapEditor.prototype.itemRect = function(index) {
return {
'x' : this.offsetX + (index % 3) * 40,
'y' : Math.floor(index / 3) * 50,
'w' : 40,
'h' : 50
};
}
dynamicMapEditor.prototype.refreshToolBox = function() {
if (!this.isUsingTool) return;
core.fillRect(this.canvas, 0, 0, this.dom.width, this.dom.height, '#000000');
var startIndex = this.pageId * this.pageMaxItems;
for (var i = 0; i < this.pageMaxItems; ++i) {
var item = this.items[startIndex + i];
if (!item) break;
var rect = this.itemRect(i);
if (item.image) core.drawImage(this.canvas, item.image, 0, item.height * item.posY, 32, 32, rect.x + 4, rect.y, 32, 32);
if (item.name) {
this.canvas.textAlign = 'center';
core.fillText(this.canvas, item.name, rect.x + 20, rect.y + 44, '#FFFFFF', '11px Verdana', 40);
}
if (core.material.enemys[item.id]) {
this.canvas.textAlign = 'left';
var damageString = core.enemys.getDamageString(item.id);
core.fillBoldText(this.canvas, damageString.damage, rect.x + 5, rect.y + 31, damageString.color, null, '11px Verdana');
var critical = core.enemys.nextCriticals(item.id, 1);
critical = core.formatBigNumber((critical[0]||[])[0], true);
if (critical == '???') critical = '?';
core.fillBoldText(this.canvas, critical, rect.x+5, rect.y+21, '#FFFFFF');
}
}
this.canvas.textAlign = 'center';
this.canvas.fillStyle = '#FFFFFF';
if(this.pageId > 0) core.fillText(this.canvas, '上一页', this.offsetX + 20, 365, '#FFFFFF', '11px Verdana');
if(this.pageId < this.pageMax-1) core.fillText(this.canvas, '下一页',this.offsetX + 100, 365, '#FFFFFF', '11px Verdana');
core.fillText(this.canvas, '帮助', this.offsetX + 60, 365, '#FFFFFF');
var text1 = core.formatBigNumber(core.getRealStatus('hp'), true) + "/" +
core.formatBigNumber(core.getRealStatus('atk'), true) + "/" +
core.formatBigNumber(core.getRealStatus("def"), true) + "/" +
core.formatBigNumber(core.getRealStatus("mdef"), true);
core.fillText(this.canvas, text1, this.offsetX + 60, 380, '#FF7F00', '11px Verdana', 120);
var text2 = core.formatBigNumber(core.getRealStatus('money', true)) + "/" +
core.formatBigNumber(core.getRealStatus('exp'), true) + "/" +
core.itemCount('yellowKey') + '/' + core.itemCount('blueKey') + '/' +
core.itemCount('redKey');
core.fillText(this.canvas, text2, this.offsetX + 60, 395, '#FF7F00', '11px Verdana', 120);
var text3 = core.itemCount('pickaxe') + '/' + core.itemCount('bomb') + '/' +
core.itemCount('centerFly');
if (core.hasFlag('poison')) text3 += "/毒";
if (core.hasFlag('weak')) text3 += "/衰";
if (core.hasFlag('curse')) text3 += "/咒";
core.fillText(this.canvas, text3, this.offsetX + 60, 410, '#FF7F00', '11px Verdana', 120);
if(this.selectedItem) {
var rect = this.itemRect(this.selectedIndex);
core.strokeRect(this.canvas, rect.x, rect.y, rect.w, rect.h, '#FF7F00', 4);
}
}
dynamicMapEditor.prototype.showInitHelp = function () {
if (main.mode != 'play' || core.getLocalStorage('_dynamicMapEditor_init')) return;
var text = "新拓展:运行时动态编辑地图!\n\n在此状态下你可以一边游戏一边编辑地图或者修改数据。\n\n";
text += "进游戏后按 [ 键可以激活,快来尝试吧!\n\n";
text += "点取消后将不再提示本页面。";
core.myconfirm(text, null, function () {
core.setLocalStorage('_dynamicMapEditor_init', true);
if (core.firstData.name != 'template') {
localStorage.removeItem('template__dynamicMapEditor_init');
localStorage.removeItem('template__dynamicMapEditor_help');
}
});
}
dynamicMapEditor.prototype.showHelp = function (fromButton) {
if (main.mode != 'play' || (!fromButton && core.getLocalStorage('_dynamicMapEditor_help'))) return;
var text = "欢迎使用黄鸡编写的运行时编辑拓展!你可以一边游戏一边编辑地图或者修改数据。\n\n";
text += "基本操作:\n - 点击图块再点地图可以放置;\n - 双击图块可以编辑数据;\n";
text += " - [ 键将开关此模式;\n - ] 键将会把改动保存到文件;\n - \\ 键将撤销上步操作。\n";
text += " - Alt+0~9 保存当前图块 \n - 0~9 读取当前图块\n";
text += "最下面三行数据分别是:\n"
text += "血攻防护盾金经黄蓝红破炸飞和debuff。";
if (!fromButton) text += "\n\n点取消将不再提示本页面。";
core.myconfirm(text, null, function () {
if (!fromButton) core.setLocalStorage("_dynamicMapEditor_help", true);
})
}
// ------ save
dynamicMapEditor.prototype.applyCurrentChange = function() {
this.saveEnemys();
this.saveValues();
this.saveFloors();
this.enemyModified = false;
this.valueModified = false;
this.mapRecord = {};
core.drawTip('已将所有改动应用到文件,记得刷新编辑器哦');
}
dynamicMapEditor.prototype.saveEnemys = function () {
if (!this.enemyModified) return;
core.enemys.enemys = core.clone(core.material.enemys);
var datastr = 'var enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80 = \n';
var emap = {};
var estr = JSON.stringify(core.enemys.enemys, function (k, v) {
var t = core.clone(v);
if (t.hp != null) {
delete t.id;
var id_ = ":" + k + ":";
emap[id_] = JSON.stringify(t);
return id_;
} else return t;
}, '\t');
for (var id_ in emap) {
estr = estr.replace('"' + id_ + '"', emap[id_])
}
datastr += estr;
fs.writeFile('project/enemys.js', core.encodeBase64(datastr), 'base64', function (e, d) {});
}
dynamicMapEditor.prototype.saveValues = function () {
if (!this.valueModified) return;
core.data.values = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.values = core.clone(core.values);
var datastr = 'var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = \n' +
JSON.stringify(data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d, null, '\t');
fs.writeFile('project/data.js', core.encodeBase64(datastr), 'base64', function (e, d) {});
}
dynamicMapEditor.prototype.saveFloors = function () {
if (Object.keys(this.mapRecord).length == 0) return;
core.initStatus.maps = core.maps._initMaps();
for (var floorId in this.mapRecord) {
if (this.mapRecord[floorId]) {
this.saveFloor(floorId);
}
}
}
dynamicMapEditor.prototype.saveFloor = function (floorId) {
var floorData = core.floors[floorId];
var filename = 'project/floors/' + floorId + '.js';
var datastr = ['main.floors.', floorId, '=\n'];
var tempJsonObj = core.clone(floorData);
var tempMap = [['map', ':map:'], ['bgmap', ':bgmap:'], ['fgmap', ':fgmap:']];
tempMap.forEach(function (v) {
v[2] = tempJsonObj[v[0]];
tempJsonObj[v[0]] = v[1];
});
var tempJson = JSON.stringify(tempJsonObj, null, 4);
tempMap.forEach(function (v) {
tempJson = tempJson.replace('"' + v[1] + '"', '[\n' + this.formatMap(v[2], v[0] != 'map') + '\n]')
}, this);
datastr = datastr.concat([tempJson]);
datastr = datastr.join('');
fs.writeFile(filename, core.encodeBase64(datastr), 'base64', function (e, d) {});
}
dynamicMapEditor.prototype.formatMap = function (mapArr, trySimplify) {
if (!mapArr || JSON.stringify(mapArr) == JSON.stringify([])) return '';
if (trySimplify) {
//检查是否是全0二维数组
var jsoncheck = JSON.stringify(mapArr).replace(/\D/g, '');
if (jsoncheck == Array(jsoncheck.length + 1).join('0')) return '';
}
//把二维数组格式化
var formatArrStr = '';
var si = mapArr.length - 1, sk = mapArr[0].length - 1;
for (var i = 0; i <= si; i++) {
formatArrStr += ' [';
for (var k = 0; k <= sk; k++) {
var num = parseInt(mapArr[i][k]);
formatArrStr += Array(Math.max(4 - String(num).length, 0)).join(' ') + num + (k == sk ? '' : ',');
}
formatArrStr += ']' + (i == si ? '' : ',\n');
}
return formatArrStr;
}
// ------ rewrite
var dynamicMapEditor = new dynamicMapEditor();
dynamicMapEditor._resize_statusBar = core.control._resize_statusBar;
core.control._resize_statusBar = function (obj) {
dynamicMapEditor._resize_statusBar.call(this,obj);
dynamicMapEditor.refreshToolBox();
}
dynamicMapEditor.updateStatusBar = core.control.updateStatusBar;
core.control.updateStatusBar = function () {
dynamicMapEditor.refreshToolBox();
dynamicMapEditor.updateStatusBar.apply(core.control, Array.prototype.slice.call(arguments));
}

110
extensions/localSave.js Normal file
View File

@ -0,0 +1,110 @@
/**
* 离线游戏使用本地存储扩展
* 开启本拓展后将会把所有存档存至 _saves 目录下
* 需配合样板V2.8.2+使用
*/
"use strict";
(function () {
// 将这一行改成 false 可以禁用本拓展
var __enabled = true;
if (window.jsinterface || !window.fs || !__enabled) return;
function rewrite() {
core.utils._setLocalForage_set = function (name, str, callback) {
var data = LZString.compressToBase64(str);
core.saves.cache[name] = data;
fs.writeFile('_saves/' + name, data, 'utf-8', callback);
}
core.utils._getLocalForage_get = function (name, callback) {
fs.readFile('_saves/' + name, 'utf-8', function (err, data) {
if (err) return callback(err);
callback(null, data);
});
}
core.utils.decompress = function (data) {
try {
return JSON.parse(LZString.decompressFromBase64(data))
} catch (e) {
return null;
}
}
core.utils._removeLocalForage_remove = function (name, callback) {
fs.deleteFile('_saves/' + name, callback);
}
core.utils.clearLocalForage = function (callback) {
fs.deleteFile('_saves', function () {
fs.mkdir('_saves', callback);
})
}
core.utils.iterateLocalForage = function (iter, callback) {
fs.readdir('_saves', function (err, data) {
if (err) callback(err);
else {
data.forEach(function (one) {
iter(null, one, null);
});
callback();
}
});
}
core.utils.keysLocalForage = function (callback) {
fs.readdir('_saves', callback);
}
core.utils.lengthLocalForage = function (callback) {
fs.readdir('_saves', function (err, data) {
if (err) callback(err);
else callback(null, data.length);
});
}
}
var _export = function () {
var toExport = [];
localforage.iterate(function (value, key, n) {
if (value == null || !key.startsWith(core.firstData.name)) return;
value = core.decompress(value);
if (value == null) return;
var str = JSON.stringify(value).replace(/[\u007F-\uFFFF]/g, function (chr) {
return "\\u" + ("0000" + chr.charCodeAt(0).toString(16)).substr(-4)
});
str = LZString.compressToBase64(str);
toExport.push(key);
core.saves.cache[key] = str;
fs.writeFile('_saves/' + key, str, 'utf-8', function () {});
}, function () {
if (toExport.length > 0) {
alert('提示!本塔已开启存档本地化!原始存档已全部导出至 _saves/ 目录下。');
}
fs.writeFile('_saves/.exported', '1', 'utf-8', function () {});
rewrite();
core.control.getSaveIndexes(function (indexes) { core.saves.ids = indexes; });
});
}
fs.mkdir('_saves', function (err) {
if (err) return;
fs.readFile('_saves/.exported', 'utf-8', function(err, data) {
if (!err && data) {
rewrite();
core.control.getSaveIndexes(function (indexes) { core.saves.ids = indexes; });
return;
}
_export();
});
});
})();

200
index.html Normal file
View File

@ -0,0 +1,200 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv='content-type' content='text/html' charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=Edge, chrome=1'>
<meta name='author' content='ckcz123'>
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=yes'>
<title>HTML5魔塔</title>
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
<meta name="screen-orientation" content="portrait">
<meta name="full-screen" content="yes">
<meta name="browsermode" content="application">
<meta name="x5-orientation" content="portrait">
<meta name="x5-fullscreen" content="true">
<meta name="x5-page-mode" content="app">
<link type='text/css' href='styles.css' rel='stylesheet'>
</head>
<body>
<div id='startImageBackgroundDiv'>
<div id='startImageDiv'></div>
<img id='startImageLogo' />
</div>
<script>
(function () {
var startImageBackgroundDiv = document.getElementById('startImageBackgroundDiv');
var startImageLogo = document.getElementById('startImageLogo');
var startImageDiv = document.getElementById('startImageDiv');
startImageLogo.onload = function () {
startImageBackgroundDiv.style.display = 'block';
var onAnimationEnd = function () {
startImageBackgroundDiv.style.display = 'none';
startImageLogo.classList.remove("startImageAnimation");
startImageDiv.classList.remove("startImageDivAnimation");
}
startImageDiv.addEventListener("webkitAnimationEnd", onAnimationEnd);
startImageDiv.addEventListener("animationend", onAnimationEnd);
startImageLogo.classList.add("startImageAnimation");
startImageDiv.classList.add("startImageDivAnimation");
// 注释下面这句话以禁止单击立刻跳过开场动画
startImageBackgroundDiv.onclick = onAnimationEnd;
}
startImageLogo.onerror = function () {}
startImageLogo.src = "logo.png";
})();
</script>
<!-- injection -->
<div id='gameGroup'>
<p id='mainTips'>请稍候...</p>
<img id='musicBtn'>
<div id='startPanel'>
<div id='startTop'>
<div id='startTopProgressBar'>
<div id='startTopProgress'></div>
</div>
<p id='startTopLoadTips'>资源即将开始加载</p>
<p id='startTopHint'>HTML5魔塔游戏平台享受更多魔塔游戏<br/>https://h5mota.com/</p>
</div>
<img id='startBackground'>
<p id='startLogo'></p>
<div id='startButtonGroup'>
<div id='startButtons'>
<span class='startButton' id='playGame'>开始游戏</span>
<span class='startButton' id='loadGame'>载入游戏</span>
<span class='startButton' id='replayGame'>录像回放</span>
</div>
<div id='levelChooseButtons'></div>
</div>
</div>
<div id='floorMsgGroup'>
<p id='logoLabel'></p>
<p id='versionLabel'></p>
<p id='floorNameLabel'></p>
</div>
<div id='statusBar' class="clearfix">
<div class="status" id="floorCol">
<img id="img-floor">
<p class='statusLabel statusText' id='floor'></p>
</div>
<div class="status" id="nameCol">
<img id="img-name">
<p class='statusLabel statusText' id='name'></p>
</div>
<div class="status" id="lvCol">
<img id="img-lv">
<p class='statusLabel statusText' id='lv'></p>
</div>
<div class="status" id='hpmaxCol'>
<img id="img-hpmax">
<p class='statusLabel statusText' id='hpmax'></p>
</div>
<div class="status" id='hpCol'>
<img id="img-hp">
<p class='statusLabel statusText' id='hp'></p>
</div>
<div class="status" id='manaCol'>
<img id="img-mana">
<p class='statusLabel statusText' id='mana'></p>
</div>
<div class="status" id='atkCol'>
<img id="img-atk">
<p class='statusLabel statusText' id='atk'></p>
</div>
<div class="status" id='defCol'>
<img id="img-def">
<p class='statusLabel statusText' id='def'></p>
</div>
<div class="status" id="mdefCol">
<img id="img-mdef">
<p class='statusLabel statusText' id='mdef'></p>
</div>
<div class="status" id="moneyCol">
<img id="img-money">
<p class='statusLabel statusText' id='money'></p>
</div>
<div class="status" id="expCol">
<img id="img-exp">
<p class='statusLabel statusText' id='exp'></p>
</div>
<div class="status" id="upCol">
<img id="img-up">
<p class='statusLabel statusText' id='up'></p>
</div>
<div class="status" id="skillCol">
<img id="img-skill">
<p class='statusLabel statusText' id='skill' style='font-style: normal'></p>
</div>
<div class="status" id='keyCol'>
<span class='statusLabel' id='yellowKey' style="color:#FFCCAA"></span>
<span class='statusLabel' id='blueKey' style="color:#AAAADD"></span>
<span class='statusLabel' id='redKey' style="color:#FF8888"></span>
<span class='statusLabel' id='greenKey' style="color:#88FF88"></span>
</div>
<div class="status" id='pzfCol'>
<span class='statusLabel' id='pickaxe' style="color: #BC6E27"></span>
<span class='statusLabel' id='bomb' style="color: #FA14B9"></span>
<span class='statusLabel' id='fly' style="color: #8DB600"></span>
</div>
<div class="status" id="debuffCol">
<span class='statusLabel' id='poison' style="color: #AFFCA8;"></span>
<span class='statusLabel' id='weak' style="color: #FECCD0;"></span>
<span class='statusLabel' id='curse' style="color: #C2F4E7;"></span>
</div>
<!-- 状态栏canvas化 -->
<canvas id="statusCanvas" style="position: absolute; left: 0; top: 0;"></canvas>
</div>
<div id="toolBar" class="clearfix">
<img class="tools" id='img-book'>
<img class="tools" id='img-fly'>
<img class="tools" id='img-toolbox'>
<img class="tools" id='img-keyboard'>
<img class="tools" id='img-shop'>
<img class="tools" id='img-save'>
<img class="tools" id='img-load'>
<img class="tools" id='img-settings'>
<img class="tools" id='img-btn1' style='display:none'>
<img class="tools" id='img-btn2' style='display:none'>
<img class="tools" id='img-btn3' style='display:none'>
<img class="tools" id='img-btn4' style='display:none'>
<img class="tools" id='img-btn5' style='display:none'>
<img class="tools" id='img-btn6' style='display:none'>
<img class="tools" id='img-btn7' style='display:none'>
<img class="tools" id='img-btn8' style='display:none'>
<p class="statusLabel tools" id="hard"></p>
</div>
<div id="gameDraw">
<div id="gif"></div>
<div id="gif2"></div>
<canvas class='gameCanvas' id='bg'></canvas>
<canvas class='gameCanvas' id='event'></canvas>
<canvas class='gameCanvas' id='hero'></canvas>
<canvas class='gameCanvas' id='event2'></canvas>
<canvas class='gameCanvas' id='fg'></canvas>
<canvas class='gameCanvas' id='damage'></canvas>
<canvas class='gameCanvas' id='animate'></canvas>
<canvas class='gameCanvas' id='curtain'></canvas>
<canvas class='gameCanvas' id='ui'></canvas>
<canvas class='gameCanvas' id='data'>此浏览器不支持HTML5</canvas>
<div id="next"></div>
</div>
</div>
<div id='inputDiv'>
<div id='inputDialog'>
<p id="inputMessage">请输入文字...</p>
<input id='inputBox' type="text" autocomplete="off"/>
<button id='inputYes'>确定</button>
<button id='inputNo'>取消</button>
</div>
</div>
<div id="ui-editor"></div>
<!-- injection -->
<script src='libs/thirdparty/lz-string.min.js'></script>
<script src='libs/thirdparty/priority-queue.min.js'></script>
<script src='libs/thirdparty/localforage.min.js'></script>
<script src='libs/thirdparty/zip.min.js'></script>
<script id='mainScript' src='main.js'></script>
<script>main.init('play');main.listen();</script>
</body>
</html>

3165
libs/actions.js Normal file

File diff suppressed because it is too large Load Diff

3558
libs/control.js Normal file

File diff suppressed because it is too large Load Diff

547
libs/core.js Normal file
View File

@ -0,0 +1,547 @@
/**
* 初始化 start
*/
"use strict";
// /**
// * @type {CoreMixin}
// */
// const core = (() => {
function core () {
this._WIDTH_ = 13;
this._HEIGHT_ = 13;
this._PX_ = this._WIDTH_ * 32;
this._PY_ = this._HEIGHT_ * 32;
this._HALF_WIDTH_ = Math.floor(this._WIDTH_ / 2);
this._HALF_HEIGHT_ = Math.floor(this._HEIGHT_ / 2);
this.__SIZE__ = main.mode == 'editor' ? 15 : this._HEIGHT_;
this.__PIXELS__ = this.__SIZE__ * 32;
this.__HALF_SIZE__ = Math.floor(this.__SIZE__ / 2);
this.material = {
'animates': {},
'images': {},
'bgms': {},
'sounds': {},
'items': {},
'enemys': {},
'icons': {},
'ground': null,
'grundCanvas': null,
'groundPattern': null,
'autotileEdges': {},
}
this.timeout = {
'turnHeroTimeout': null,
'onDownTimeout': null,
'sleepTimeout': null,
}
this.interval = {
'heroMoveInterval': null,
'onDownInterval': null,
}
this.animateFrame = {
'totalTime': 0,
'totalTimeStart': 0,
'globalAnimate': false,
'globalTime': 0,
'selectorTime': 0,
'selectorUp': true,
'animateTime': 0,
'moveTime': 0,
'lastLegTime': 0,
'leftLeg': true,
'weather': {
'time': 0,
'type': null,
'level': 1,
'nodes': [],
'data': null,
'fog': null,
'cloud': null,
'sun': null
},
"tip": null,
"asyncId": {},
"lastAsyncId": null
}
this.musicStatus = {
'audioContext': null, // WebAudioContext
'bgmStatus': false, // 是否播放BGM
'soundStatus': true, // 是否播放SE
'playingBgm': null, // 正在播放的BGM
'pauseTime': 0, // 上次暂停的时间
'lastBgm': null, // 上次播放的bgm
'gainNode': null,
'playingSounds': {}, // 正在播放的SE
'userVolume': 1.0, // 用户音量
'designVolume': 1.0, //设计音量
'bgmSpeed': 100, // 背景音乐速度
'bgmUsePitch': null, // 是否同时修改音调
'cachedBgms': [], // 缓存BGM内容
'cachedBgmCount': 8, // 缓存的bgm数量
}
this.platform = {
'isOnline': true, // 是否http
'isPC': true, // 是否是PC
'isAndroid': false, // 是否是Android
'isIOS': false, // 是否是iOS
'string': 'PC',
'isWeChat': false, // 是否是微信
'isQQ': false, // 是否是QQ
'isChrome': false, // 是否是Chrome
'supportCopy': false, // 是否支持复制到剪切板
'fileInput': null, // FileInput
'fileReader': null, // 是否支持FileReader
'successCallback': null, // 读取成功
'errorCallback': null, // 读取失败
}
// 样式
this.domStyle = {
scale: 1.0,
ratio: 1.0,
hdCanvas: ["damage", "ui", "data"],
availableScale: [],
isVertical: false,
showStatusBar: true,
toolbarBtn: false,
}
this.bigmap = {
canvas: ["bg", "event", "event2", "fg", "damage"],
offsetX: 0, // in pixel
offsetY: 0,
posX: 0, //
posY: 0,
width: main.mode == 'editor' ? this.__SIZE__ : this._WIDTH_, // map width and height
height: main.mode == 'editor' ? this.__SIZE__ : this._HEIGHT_,
v2: false,
threshold: 1024,
extend: 10,
scale: 1.0,
tempCanvas: null, // A temp canvas for drawing
cacheCanvas: null, // A cache canvas
}
this.saves = {
"saveIndex": null,
"ids": {},
"autosave": {
"data": null,
"time": 0,
"updated": false,
"storage": true, // 是否把自动存档写入文件a
"max": 20, // 自动存档最大回退数
"now": 0,
},
"favorite": [],
"favoriteName": {},
"cache": {}
}
this.initStatus = {
'played': false,
'gameOver': false,
// 勇士属性
'hero': {},
'heroCenter': { 'px': null, 'py': null },
// 当前地图
'floorId': null,
'thisMap': null,
'maps': null,
'bgmaps': {},
'fgmaps': {},
'mapBlockObjs': {},
'checkBlock': {}, // 每个点的阻激夹域信息
'damage': { // 每个点的显伤绘制
'posX': 0,
'posY': 0,
'data': [],
'extraData': [],
},
'lockControl': false,
// 勇士移动状态
'heroMoving': 0,
'heroStop': true,
// 自动寻路相关
'automaticRoute': {
'autoHeroMove': false,
'autoStep': 0,
'movedStep': 0,
'destStep': 0,
'destX': null,
'destY': null,
'offsetX': null,
'offsetY': null,
'autoStepRoutes': [],
'moveStepBeforeStop': [],
'lastDirection': null,
'cursorX': 0,
'cursorY': 0,
"moveDirectly": false,
},
// 按下键的时间:为了判定双击
'downTime': null,
'ctrlDown': false,
'preview': {
'enabled': false,
'prepareDragging': false,
'dragging': false,
'px': 0,
'py': 0,
},
// 路线&回放
'route': [],
'replay': {
'replaying': false,
'pausing': false,
'animate': false, // 正在某段动画中
'failed': false,
'toReplay': [],
'totalList': [],
'speed': 1.0,
'steps': 0,
'save': [],
},
// 录像折叠
'routeFolding': {},
// event事件
'shops': {},
'event': {
'id': null,
'data': null,
'selection': null,
'ui': null,
'interval': null,
},
'autoEvents': [],
'textAttribute': {
'position': "center",
"offset": 0,
"title": [255, 215, 0, 1],
"background": [0, 0, 0, 0.85],
"text": [255, 255, 255, 1],
"titlefont": 22,
"textfont": 16,
"bold": false,
"time": 0,
"letterSpacing": 0,
"animateTime": 0,
},
"globalAttribute": {
'equipName': main.equipName || [],
"statusLeftBackground": main.styles.statusLeftBackground || "url(project/materials/ground.png) repeat",
"statusTopBackground": main.styles.statusTopBackground || "url(project/materials/ground.png) repeat",
"toolsBackground": main.styles.toolsBackground || "url(project/materials/ground.png) repeat",
"borderColor": main.styles.borderColor || [204, 204, 204, 1],
"statusBarColor": main.styles.statusBarColor || [255, 255, 255, 1],
"floorChangingStyle": main.styles.floorChangingStyle || "background-color: black; color: white",
"selectColor": main.styles.selectColor || [255, 215, 0, 1],
"font": main.styles.font || "Verdana"
},
'curtainColor': null,
// 动画
'globalAnimateObjs': [],
'floorAnimateObjs': [],
'boxAnimateObjs': [],
'autotileAnimateObjs': [],
"globalAnimateStatus": 0,
'animateObjs': [],
};
// 标记的楼层列表,用于数据统计
this.markedFloorIds = {};
this.status = {};
this.dymCanvas = {};
if (main.mode == 'editor') {
document.documentElement.style.setProperty('--size', this.__SIZE__);
document.documentElement.style.setProperty('--pixel', this.__PIXELS__ + 'px');
}
}
/////////// 系统事件相关 ///////////
////// 初始化 //////
core.prototype.init = function (coreData, callback) {
this._forwardFuncs();
for (var key in coreData)
core[key] = coreData[key];
this._init_flags();
this._init_platform();
this._init_others();
this._init_plugins();
var b = main.mode == 'editor';
// 初始化画布
for (var name in core.canvas) {
if (core.domStyle.hdCanvas.indexOf(name) >= 0)
core.maps._setHDCanvasSize(core.canvas[name], b ? core.__PIXELS__ : core._PX_, b ? core.__PIXELS__ : core._PY_);
else {
core.canvas[name].canvas.width = (b ? core.__PIXELS__ : core._PX_);
core.canvas[name].canvas.height = (b ? core.__PIXELS__ : core._PY_);
}
}
core.loader._load(function () {
core.extensions._load(function () {
core._afterLoadResources(callback);
});
});
core.dom.musicBtn.style.display = 'block';
core.setMusicBtn();
}
core.prototype._init_flags = function () {
core.flags = core.clone(core.data.flags);
core.values = core.clone(core.data.values);
core.firstData = core.clone(core.data.firstData);
this._init_sys_flags();
// 让你总是拼错!
window.on = true;
window.off = false;
window.ture = true;
window.flase = false;
core.dom.versionLabel.innerText = core.firstData.version;
core.dom.logoLabel.innerText = core.firstData.title;
document.title = core.firstData.title + " - HTML5魔塔";
document.getElementById("startLogo").innerText = core.firstData.title;
(core.firstData.shops || []).forEach(function (t) { core.initStatus.shops[t.id] = t; });
core.maps._initFloors();
// 初始化怪物、道具等
core.material.enemys = core.enemys.getEnemys();
core.material.items = core.items.getItems();
core.material.icons = core.icons.getIcons();
// 初始化自动事件
for (var floorId in core.floors) {
var autoEvents = core.floors[floorId].autoEvent || {};
for (var loc in autoEvents) {
var locs = loc.split(","), x = parseInt(locs[0]), y = parseInt(locs[1]);
for (var index in autoEvents[loc]) {
var autoEvent = core.clone(autoEvents[loc][index]);
if (autoEvent && autoEvent.condition && autoEvent.data) {
autoEvent.floorId = floorId;
autoEvent.x = x;
autoEvent.y = y;
autoEvent.index = index;
autoEvent.symbol = floorId + "@" + x + "@" + y + "@" + index;
autoEvent.condition = core.replaceValue(autoEvent.condition);
autoEvent.data = core.precompile(autoEvent.data);
core.initStatus.autoEvents.push(autoEvent);
}
}
}
}
// 道具的穿上/脱下,视为自动事件
for (var equipId in core.material.items) {
var equip = core.material.items[equipId];
if (equip.cls != 'equips' || !equip.equip) continue;
if (!equip.equip.equipEvent && !equip.equip.unequipEvent) continue;
var equipFlag = '_equipEvent_' + equipId;
var autoEvent1 = {
symbol: "_equipEvent_" + equipId,
currentFloor: false,
multiExecute: true,
condition: "core.hasEquip('" + equipId + "') && !core.hasFlag('" + equipFlag + "')",
data: core.precompile([{ "type": "setValue", "name": "flag:" + equipFlag, "value": "true" }].concat(equip.equip.equipEvent || [])),
};
var autoEvent2 = {
symbol: "_unequipEvent_" + equipId,
currentFloor: false,
multiExecute: true,
condition: "!core.hasEquip('" + equipId + "') && core.hasFlag('" + equipFlag + "')",
data: core.precompile([{ "type": "setValue", "name": "flag:" + equipFlag, "value": "null" }].concat(equip.equip.unequipEvent || [])),
};
core.initStatus.autoEvents.push(autoEvent1);
core.initStatus.autoEvents.push(autoEvent2);
}
core.initStatus.autoEvents.sort(function (e1, e2) {
if (e1.floorId == null) return 1;
if (e2.floorId == null) return -1;
if (e1.priority != e2.priority) return e2.priority - e1.priority;
if (e1.floorId != e2.floorId) return core.floorIds.indexOf(e1.floorId) - core.floorIds.indexOf(e2.floorId);
if (e1.x != e2.x) return e1.x - e2.x;
if (e1.y != e2.y) return e1.y - e2.y;
return e1.index - e2.index;
})
}
core.prototype._init_sys_flags = function () {
if (core.flags.equipboxButton) core.flags.equipment = true;
core.flags.displayEnemyDamage = core.getLocalStorage('enemyDamage', true);
core.flags.displayCritical = core.getLocalStorage('critical', true);
core.flags.displayExtraDamage = core.getLocalStorage('extraDamage', true);
core.flags.enableEnemyPoint = core.getLocalStorage('enableEnemyPoint', core.flags.enableEnemyPoint);
core.flags.leftHandPrefer = core.getLocalStorage('leftHandPrefer', false);
core.flags.extraDamageType = core.getLocalStorage('extraDamageType', 2);
// 行走速度
core.values.moveSpeed = core.getLocalStorage('moveSpeed', core.values.moveSpeed || 100);
core.values.floorChangeTime = core.getLocalStorage('floorChangeTime', core.values.floorChangeTime);
if (core.values.floorChangeTime == null) core.values.floorChangeTime = 500;
core.flags.enableHDCanvas = core.getLocalStorage('enableHDCanvas', !core.platform.isIOS);
}
core.prototype._init_platform = function () {
core.platform.isOnline = location.protocol.indexOf("http") == 0;
if (!core.platform.isOnline) alert("请勿直接打开html文件使用启动服务或者APP进行离线游戏。");
window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;
core.musicStatus.bgmStatus = core.getLocalStorage('bgmStatus', true);
core.musicStatus.soundStatus = core.getLocalStorage('soundStatus', true);
//新增 userVolume 默认值0.7
core.musicStatus.userVolume = core.getLocalStorage('userVolume', 0.7);
try {
core.musicStatus.audioContext = new window.AudioContext();
core.musicStatus.gainNode = core.musicStatus.audioContext.createGain();
core.musicStatus.gainNode.gain.value = core.musicStatus.userVolume;
core.musicStatus.gainNode.connect(core.musicStatus.audioContext.destination);
} catch (e) {
console.log("该浏览器不支持AudioContext");
core.musicStatus.audioContext = null;
}
["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"].forEach(function (t) {
if (navigator.userAgent.indexOf(t) >= 0) {
if (t == 'iPhone' || t == 'iPad' || t == 'iPod') core.platform.isIOS = true;
if (t == 'Android') core.platform.isAndroid = true;
core.platform.isPC = false;
}
});
core.platform.string = core.platform.isPC ? "PC" : core.platform.isAndroid ? "Android" : core.platform.isIOS ? "iOS" : "";
core.platform.supportCopy = document.queryCommandSupported && document.queryCommandSupported("copy");
var chrome = /Chrome\/(\d+)\./i.exec(navigator.userAgent);
if (chrome && parseInt(chrome[1]) >= 50) core.platform.isChrome = true;
core.platform.isSafari = /Safari/i.test(navigator.userAgent) && !/Chrome/i.test(navigator.userAgent);
core.platform.isQQ = /QQ/i.test(navigator.userAgent);
core.platform.isWeChat = /MicroMessenger/i.test(navigator.userAgent);
if (window.FileReader) {
core.platform.fileReader = new FileReader();
core.platform.fileReader.onload = function () {
core.readFileContent(core.platform.fileReader.result);
};
core.platform.fileReader.onerror = function () {
if (core.platform.errorCallback)
core.platform.errorCallback();
}
}
core.flags.enableHDCanvas = core.getLocalStorage('enableHDCanvas', !core.platform.isIOS);
if (main.mode != 'editor') {
core.domStyle.scale = core.getLocalStorage('scale', 1);
if (core.flags.enableHDCanvas) core.domStyle.ratio = Math.max(window.devicePixelRatio || 1, core.domStyle.scale);
}
}
core.prototype._init_others = function () {
// 一些额外的东西
core.material.groundCanvas = document.createElement('canvas').getContext('2d');
core.material.groundCanvas.canvas.width = core.material.groundCanvas.canvas.height = 32;
core.material.groundPattern = core.material.groundCanvas.createPattern(core.material.groundCanvas.canvas, 'repeat');
core.bigmap.tempCanvas = document.createElement('canvas').getContext('2d');
core.bigmap.cacheCanvas = document.createElement('canvas').getContext('2d');
core.loadImage("materials", 'fog', function (name, img) { core.animateFrame.weather.fog = img; });
core.loadImage("materials", "cloud", function (name, img) { core.animateFrame.weather.cloud = img; })
core.loadImage("materials", "sun", function (name, img) { core.animateFrame.weather.sun = img; })
core.loadImage("materials", 'keyboard', function (name, img) { core.material.images.keyboard = img; });
// 记录存档编号
core.saves.saveIndex = core.getLocalStorage('saveIndex', 1);
core.control.getSaveIndexes(function (indexes) { core.saves.ids = indexes; });
}
core.prototype._afterLoadResources = function (callback) {
// 初始化地图
core.initStatus.maps = core.maps._initMaps();
core.control._setRequestAnimationFrame();
// 图片裁剪
(main.splitImages || []).forEach(function (one) {
var name = core.getMappedName(one.name);
if (!core.material.images.images[name]) {
console.warn('找不到图片:' + name + ',无法裁剪');
return;
}
if (!name.endsWith('.png')) {
console.warn('无法裁剪非png格式图片' + name);
return;
}
var arr = core.splitImage(core.material.images.images[name], one.width, one.height);
for (var i = 0; i < arr.length; ++i) {
core.material.images.images[(one.prefix || "") + i + '.png'] = arr[i];
}
});
if (core.plugin._afterLoadResources)
core.plugin._afterLoadResources();
core.showStartAnimate();
if (callback) callback();
}
core.prototype._init_plugins = function () {
core.plugin = new function () { };
for (var name in plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1) {
if (plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1[name] instanceof Function) {
try {
plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1[name].apply(core.plugin);
}
catch (e) {
console.error(e);
console.error("无法初始化插件" + name);
}
}
}
core._forwardFunc("plugin");
}
core.prototype._forwardFuncs = function () {
for (var i = 0; i < main.loadList.length; ++i) {
var name = main.loadList[i];
if (name == 'core') continue;
this._forwardFunc(name);
}
}
core.prototype._forwardFunc = function (name, funcname) {
if (funcname == null) {
for (funcname in core[name]) {
if (funcname.charAt(0) != "_" && core[name][funcname] instanceof Function) {
this._forwardFunc(name, funcname);
}
}
return;
}
if (core[funcname]) {
console.error("ERROR: 无法转发 " + name + " 中的函数 " + funcname + " 到 core 中!同名函数已存在。");
return;
}
var parameterInfo = /^\s*function\s*[\w_$]*\(([\w_,$\s]*)\)\s*\{/.exec(core[name][funcname].toString());
var parameters = (parameterInfo == null ? "" : parameterInfo[1]).replace(/\s*/g, '').replace(/,/g, ', ');
// core[funcname] = new Function(parameters, "return core."+name+"."+funcname+"("+parameters+");");
eval("core." + funcname + " = function (" + parameters + ") {\n\treturn core." + name + "." + funcname + ".apply(core." + name + ", arguments);\n}");
}
core.prototype.doFunc = function (func, _this) {
if (typeof func == 'string') {
func = core.plugin[func];
_this = core.plugin;
}
return func.apply(_this, Array.prototype.slice.call(arguments, 2));
}
// return new Core();
// })();
var core = new core();

13
libs/data.js Normal file
View File

@ -0,0 +1,13 @@
"use strict";
function data () {
this._init();
}
data.prototype._init = function () {
this.firstData = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData;
this.values = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.values;
this.flags = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.flags;
//delete(data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d);
}

523
libs/enemys.js Normal file
View File

@ -0,0 +1,523 @@
"use strict";
function enemys () {
this._init();
}
////// 初始化 //////
enemys.prototype._init = function () {
this.enemys = enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80;
this.enemydata = functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a.enemys;
for (var enemyId in this.enemys) {
this.enemys[enemyId].id = enemyId;
}
if (main.mode == 'play') {
this.enemydata.hasSpecial = function (a, b) {
return core.enemys.hasSpecial(a, b)
};
}
}
enemys.prototype.getEnemys = function () {
var enemys = core.clone(this.enemys);
var enemyInfo = core.getFlag('enemyInfo');
if (enemyInfo) {
for (var id in enemyInfo) {
for (var name in enemyInfo[id]) {
enemys[id][name] = core.clone(enemyInfo[id][name]);
}
}
}
// 将所有怪物的各项属性映射到朝下的
for (var id in enemys) {
if (enemys[id].faceIds) {
var downId = enemys[id].faceIds.down;
if (downId != null && downId != id && enemys[downId]) {
enemys[id] = { id: id };
for (var property in enemys[downId]) {
if (property != 'id' && enemys[downId].hasOwnProperty(property)) {
(function (id, downId, property) {
Object.defineProperty(enemys[id], property, {
get: function () { return enemys[downId][property] },
set: function (v) { enemys[downId][property] = v },
enumerable: true
})
})(id, downId, property);
}
}
}
}
}
return enemys;
}
////// 判断是否含有某特殊属性 //////
enemys.prototype.hasSpecial = function (special, test) {
if (special == null) return false;
if (special instanceof Array) {
return special.indexOf(test) >= 0;
}
if (typeof special == 'number') {
return special === test;
}
if (typeof special == 'string') {
return this.hasSpecial(core.material.enemys[special], test);
}
if (special.special != null) {
return this.hasSpecial(special.special, test);
}
return false;
}
enemys.prototype.getSpecials = function () {
return this.enemydata.getSpecials();
}
////// 获得所有特殊属性的名称 //////
enemys.prototype.getSpecialText = function (enemy) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
if (!enemy) return [];
var special = enemy.special;
var text = [];
var specials = this.getSpecials();
if (specials) {
for (var i = 0; i < specials.length; i++) {
if (this.hasSpecial(special, specials[i][0]))
text.push(this._calSpecialContent(enemy, specials[i][1]));
}
}
return text;
}
////// 获得所有特殊属性的颜色 //////
enemys.prototype.getSpecialColor = function (enemy) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
if (!enemy) return [];
var special = enemy.special;
var colors = [];
var specials = this.getSpecials();
if (specials) {
for (var i = 0; i < specials.length; i++) {
if (this.hasSpecial(special, specials[i][0]))
colors.push(specials[i][3] || null);
}
}
return colors;
}
////// 获得所有特殊属性的额外标记 //////
enemys.prototype.getSpecialFlag = function (enemy) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
if (!enemy) return [];
var special = enemy.special;
var flag = 0;
var specials = this.getSpecials();
if (specials) {
for (var i = 0; i < specials.length; i++) {
if (this.hasSpecial(special, specials[i][0]))
flag |= (specials[i][4] || 0);
}
}
return flag;
}
////// 获得每个特殊属性的说明 //////
enemys.prototype.getSpecialHint = function (enemy, special) {
var specials = this.getSpecials();
if (special == null) {
if (specials == null) return [];
var hints = [];
for (var i = 0; i < specials.length; i++) {
if (this.hasSpecial(enemy, specials[i][0]))
hints.push("\r[" + core.arrayToRGBA(specials[i][3] || "#FF6A6A") + "]\\d" + this._calSpecialContent(enemy, specials[i][1]) +
"\\d\r[]" + this._calSpecialContent(enemy, specials[i][2]));
}
return hints;
}
if (specials == null) return "";
for (var i = 0; i < specials.length; i++) {
if (special == specials[i][0])
return "\r[#FF6A6A]\\d" + this._calSpecialContent(enemy, specials[i][1]) + "\\d\r[]" + this._calSpecialContent(enemy, specials[i][2]);
}
return "";
}
enemys.prototype._calSpecialContent = function (enemy, content) {
if (typeof content == 'string') return content;
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
if (content instanceof Function) {
return content(enemy);
}
return "";
}
////// 获得某个点上某个怪物的某项属性 //////
enemys.prototype.getEnemyValue = function (enemy, name, x, y, floorId) {
floorId = floorId || core.status.floorId;
if ((((flags.enemyOnPoint || {})[floorId] || {})[x + "," + y] || {})[name] != null) {
return flags.enemyOnPoint[floorId][x + "," + y][name];
}
if (enemy == null) {
var block = core.getBlock(x, y, floorId);
if (block == null) return null;
enemy = core.material.enemys[block.event.id];
}
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
if (enemy == null) return null;
return enemy[name];
}
////// 能否获胜 //////
enemys.prototype.canBattle = function (enemy, x, y, floorId) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
var damage = this.getDamage(enemy, x, y, floorId);
return damage != null && damage < core.status.hero.hp;
}
enemys.prototype.getDamageString = function (enemy, x, y, floorId) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
var damage = this.getDamage(enemy, x, y, floorId);
var color = '#000000';
if (damage == null) {
damage = "???";
color = '#FF2222';
}
else {
if (damage <= 0) color = '#11FF11';
else if (damage < core.status.hero.hp / 3) color = '#FFFFFF';
else if (damage < core.status.hero.hp * 2 / 3) color = '#FFFF00';
else if (damage < core.status.hero.hp) color = '#FF9933';
else color = '#FF2222';
damage = core.formatBigNumber(damage, true);
if (core.enemys.hasSpecial(enemy, 19))
damage += "+";
if (core.enemys.hasSpecial(enemy, 21))
damage += "-";
if (core.enemys.hasSpecial(enemy, 11))
damage += "^";
}
return {
"damage": damage,
"color": color
};
}
////// 接下来N个临界值和临界减伤计算 //////
enemys.prototype.nextCriticals = function (enemy, number, x, y, floorId) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
number = number || 1;
var specialCriticals = this._nextCriticals_special(enemy, number, x, y, floorId);
if (specialCriticals != null) return specialCriticals;
var info = this.getDamageInfo(enemy, null, x, y, floorId);
if (info == null) { // 如果未破防...
var overAtk = this._nextCriticals_overAtk(enemy, x, y, floorId);
if (overAtk == null) return [];
if (typeof overAtk[1] == 'number') return [[overAtk[0], -overAtk[1]]];
info = overAtk[1];
info.__over__ = true;
info.__overAtk__ = overAtk[0];
}
if (typeof info == 'number') return [[0, 0]];
if (info.damage <= 0 && !core.flags.enableNegativeDamage) {
return [[info.__overAtk__ || 0, 0]];
}
if (core.flags.useLoop) {
if (core.status.hero.atk <= (main.criticalUseLoop || 1)) {
return this._nextCriticals_useLoop(enemy, info, number, x, y, floorId);
}
else {
return this._nextCriticals_useBinarySearch(enemy, info, number, x, y, floorId);
}
}
else {
return this._nextCriticals_useTurn(enemy, info, number, x, y, floorId);
}
}
/// 未破防临界采用二分计算
enemys.prototype._nextCriticals_overAtk = function (enemy, x, y, floorId) {
var calNext = function (currAtk, maxAtk) {
var start = currAtk, end = maxAtk;
if (start > end) return null;
while (start < end) {
var mid = Math.floor((start + end) / 2);
if (mid - start > end - mid) mid--;
var nextInfo = core.enemys.getDamageInfo(enemy, { "atk": mid }, x, y, floorId);
if (nextInfo != null) end = mid;
else start = mid + 1;
}
var nextInfo = core.enemys.getDamageInfo(enemy, { "atk": start }, x, y, floorId);
return nextInfo == null ? null : [start - core.status.hero.atk, nextInfo];
}
return calNext(core.status.hero.atk + 1,
core.getEnemyValue(enemy, 'hp', x, y, floorId) + core.getEnemyValue(enemy, 'def', x, y, floorId));
}
enemys.prototype._nextCriticals_special = function (enemy, number, x, y, floorId) {
if (this.hasSpecial(enemy.special, 10) || this.hasSpecial(enemy.special, 3))
return []; // 模仿or坚固临界
return null;
}
enemys.prototype._nextCriticals_useLoop = function (enemy, info, number, x, y, floorId) {
var mon_hp = info.mon_hp, hero_atk = core.status.hero.atk, mon_def = info.mon_def, pre = info.damage;
var list = [];
var start_atk = hero_atk;
if (info.__over__) {
start_atk += info.__overAtk__;
list.push([info.__overAtk__, -info.damage]);
}
for (var atk = start_atk + 1; atk <= mon_hp + mon_def; atk++) {
var nextInfo = this.getDamageInfo(enemy, { "atk": atk }, x, y, floorId);
if (nextInfo == null || (typeof nextInfo == 'number')) break;
if (pre > nextInfo.damage) {
pre = nextInfo.damage;
list.push([atk - hero_atk, info.damage - nextInfo.damage]);
if (nextInfo.damage <= 0 && !core.flags.enableNegativeDamage) break;
if (list.length >= number) break;
}
}
if (list.length == 0) list.push([0, 0]);
return list;
}
enemys.prototype._nextCriticals_useBinarySearch = function (enemy, info, number, x, y, floorId) {
var mon_hp = info.mon_hp, hero_atk = core.status.hero.atk, mon_def = info.mon_def, pre = info.damage;
var list = [];
var start_atk = hero_atk;
if (info.__over__) {
start_atk += info.__overAtk__;
list.push([info.__overAtk__, -info.damage]);
}
var calNext = function (currAtk, maxAtk) {
var start = Math.floor(currAtk), end = Math.floor(maxAtk);
if (start > end) return null;
while (start < end) {
var mid = Math.floor((start + end) / 2);
if (mid - start > end - mid) mid--;
var nextInfo = core.enemys.getDamageInfo(enemy, { "atk": mid }, x, y, floorId);
if (nextInfo == null || (typeof nextInfo == 'number')) return null;
if (pre > nextInfo.damage) end = mid;
else start = mid + 1;
}
var nextInfo = core.enemys.getDamageInfo(enemy, { "atk": start }, x, y, floorId);
return nextInfo == null || (typeof nextInfo == 'number') || nextInfo.damage >= pre ? null : [start, nextInfo.damage];
}
var currAtk = start_atk;
while (true) {
var next = calNext(currAtk + 1, mon_hp + mon_def, pre);
if (next == null) break;
currAtk = next[0];
pre = next[1];
list.push([currAtk - hero_atk, info.damage - pre]);
if (pre <= 0 && !core.flags.enableNegativeDamage) break;
if (list.length >= number) break;
}
if (list.length == 0) list.push([0, 0]);
return list;
}
enemys.prototype._nextCriticals_useTurn = function (enemy, info, number, x, y, floorId) {
var mon_hp = info.mon_hp, hero_atk = core.status.hero.atk, mon_def = info.mon_def, turn = info.turn;
// ------ 超大回合数强制使用二分算临界
// 以避免1攻10e回合2攻5e回合导致下述循环卡死问题
if (turn >= 1e6) { // 100w回合以上强制二分计算临界
return this._nextCriticals_useBinarySearch(enemy, info, number, x, y, floorId);
}
var list = [], pre = null;
var start_atk = hero_atk;
if (info.__over__) {
start_atk += info.__overAtk__;
list.push([info.__overAtk__, -info.damage]);
}
for (var t = turn - 1; t >= 1; t--) {
var nextAtk = Math.ceil(mon_hp / t) + mon_def;
// 装备提升比例的计算临界
nextAtk = Math.ceil(nextAtk / core.getBuff('atk'));
if (nextAtk <= start_atk) break;
if (nextAtk != pre) {
var nextInfo = this.getDamageInfo(enemy, { "atk": nextAtk }, x, y, floorId);
if (nextInfo == null || (typeof nextInfo == 'number')) break;
list.push([nextAtk - hero_atk, Math.floor(info.damage - nextInfo.damage)]);
if (nextInfo.damage <= 0 && !core.flags.enableNegativeDamage) break;
pre = nextAtk;
}
if (list.length >= number)
break;
}
if (list.length == 0) list.push([0, 0]);
return list;
}
////// N防减伤计算 //////
enemys.prototype.getDefDamage = function (enemy, k, x, y, floorId) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
k = k || 1;
var nowDamage = this._getDamage(enemy, null, x, y, floorId);
var nextDamage = this._getDamage(enemy, { "def": core.status.hero.def + k }, x, y, floorId);
if (nowDamage == null || nextDamage == null) return "???";
return nowDamage - nextDamage;
}
enemys.prototype.getEnemyInfo = function (enemy, hero, x, y, floorId) {
if (enemy == null) return null;
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
return this.enemydata.getEnemyInfo(enemy, hero, x, y, floorId)
}
////// 获得战斗伤害信息(实际伤害计算函数) //////
enemys.prototype.getDamageInfo = function (enemy, hero, x, y, floorId) {
if (enemy == null) return null;
// 移动到了脚本编辑 - getDamageInfo中
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
return this.enemydata.getDamageInfo(enemy, hero, x, y, floorId);
}
////// 获得在某个勇士属性下怪物伤害 //////
enemys.prototype.getDamage = function (enemy, x, y, floorId) {
return this._getDamage(enemy, null, x, y, floorId);
}
enemys.prototype._getDamage = function (enemy, hero, x, y, floorId) {
if (enemy == null) enemy = core.getBlockId(x, y, floorId);
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
if (enemy == null) return null;
var info = this.getDamageInfo(enemy, hero, x, y, floorId);
if (info == null) return null;
if (typeof info == 'number') return info;
return info.damage;
}
////// 获得当前楼层的怪物列表 //////
enemys.prototype.getCurrentEnemys = function (floorId) {
floorId = floorId || core.status.floorId;
var enemys = [], used = {};
core.extractBlocks(floorId);
core.status.maps[floorId].blocks.forEach(function (block) {
if (!block.disable && block.event.cls.indexOf('enemy') == 0) {
this._getCurrentEnemys_addEnemy(block.event.id, enemys, used, block.x, block.y, floorId);
}
}, this);
return this._getCurrentEnemys_sort(enemys);
}
enemys.prototype._getCurrentEnemys_getEnemy = function (enemyId) {
var enemy = core.material.enemys[enemyId];
if (!enemy) return null;
// 检查朝向displayIdInBook
return core.material.enemys[enemy.displayIdInBook] || core.material.enemys[(enemy.faceIds || {}).down] || enemy;
}
enemys.prototype._getCurrentEnemys_addEnemy = function (enemyId, enemys, used, x, y, floorId) {
var enemy = this._getCurrentEnemys_getEnemy(enemyId);
if (enemy == null) return;
var id = enemy.id;
var enemyInfo = this.getEnemyInfo(enemy, null, null, null, floorId);
var locEnemyInfo = this.getEnemyInfo(enemy, null, x, y, floorId);
if (!core.flags.enableEnemyPoint ||
(locEnemyInfo.atk == enemyInfo.atk && locEnemyInfo.def == enemyInfo.def && locEnemyInfo.hp == enemyInfo.hp)) {
x = null;
y = null;
} else {
// 检查enemys里面是否使用了存在的内容
for (var i = 0; i < enemys.length; ++i) {
var one = enemys[i];
if (id == one.id && one.locs != null &&
locEnemyInfo.atk == one.atk && locEnemyInfo.def == one.def && locEnemyInfo.hp == one.hp) {
one.locs.push([x, y]);
return;
}
}
enemyInfo = locEnemyInfo;
}
var id = enemy.id + ":" + x + ":" + y;
if (used[id]) return;
used[id] = true;
var specialText = core.enemys.getSpecialText(enemy);
var specialColor = core.enemys.getSpecialColor(enemy);
var critical = this.nextCriticals(enemy, 1, x, y, floorId);
if (critical.length > 0) critical = critical[0];
var e = core.clone(enemy);
for (var v in enemyInfo) {
e[v] = enemyInfo[v];
}
if (x != null && y != null) {
e.locs = [[x, y]];
}
e.name = core.getEnemyValue(enemy, 'name', x, y, floorId);
e.specialText = specialText;
e.specialColor = specialColor;
e.damage = this.getDamage(enemy, x, y, floorId);
e.critical = critical[0];
e.criticalDamage = critical[1];
e.defDamage = this._getCurrentEnemys_addEnemy_defDamage(enemy, x, y, floorId);
enemys.push(e);
}
enemys.prototype._getCurrentEnemys_addEnemy_defDamage = function (enemy, x, y, floorId) {
var ratio = core.status.maps[floorId || core.status.floorId].ratio || 1;
return this.getDefDamage(enemy, ratio, x, y, floorId);
}
enemys.prototype._getCurrentEnemys_sort = function (enemys) {
return enemys.sort(function (a, b) {
if (a.damage == b.damage) {
return a.money - b.money;
}
if (a.damage == null) {
return 1;
}
if (b.damage == null) {
return -1;
}
return a.damage - b.damage;
});
}
enemys.prototype.hasEnemyLeft = function (enemyId, floorId) {
if (floorId == null) floorId = core.status.floorId;
if (!(floorId instanceof Array)) floorId = [floorId];
var enemyMap = {};
if (enemyId instanceof Array) enemyId.forEach(function (v) { enemyMap[v] = true; });
else if (enemyId) enemyMap[enemyId] = true;
else enemyMap = null;
for (var i = 0; i < floorId.length; i++) {
core.extractBlocks(floorId[i]);
var mapBlocks = core.status.maps[floorId[i]].blocks;
for (var b = 0; b < mapBlocks.length; b++) {
if (!mapBlocks[b].disable && mapBlocks[b].event.cls.indexOf('enemy') === 0) {
if (enemyMap === null || enemyMap[core.getFaceDownId(mapBlocks[b])]) return true;
}
}
}
return false;
}

3788
libs/events.js Normal file

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More