2 Commits

Author SHA1 Message Date
walkpan
bfcd82960a feat(resources): 添加位图字体资源文件
添加 Ifont 位图字体资源,包含纹理图集、字体定义文件及元数据。
更新 UI 图片资源。
2026-04-02 08:11:45 +08:00
walkpan
5686adc79d feat(任务卡): 允许在英雄满员时通过合并规则使用英雄卡
当英雄数量达到上限时,检查新英雄卡是否符合合并规则。如果满足相同英雄和等级的数量要求,则允许使用该卡进行合并升级,避免因上限限制而无法使用英雄卡。
2026-04-02 08:11:36 +08:00
11 changed files with 4815 additions and 1683 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

After

Width:  |  Height:  |  Size: 252 KiB

View File

@@ -0,0 +1,14 @@
info aa=1 size=32 smooth=1 stretchH=100 bold=0 padding=0,0,0,0 spacing=1,1 charset="" italic=0 unicode=1 face="Arial" outline=0
common lineHeight=32 base=26 scaleW=995 scaleH=411 pages=1 packed=0 alphaChnl=1 redChnl=0 greenChnl=0 blueChnl=0
page id=0 file="Ifont0.png"
chars count=10
char id=65 x=5 y=5 width=160 height=198 xoffset=0 yoffset=-83 xadvance=160 page=0 chnl=15
char id=65 x=170 y=5 width=160 height=198 xoffset=0 yoffset=-83 xadvance=160 page=0 chnl=15
char id=65 x=335 y=5 width=160 height=198 xoffset=0 yoffset=-83 xadvance=160 page=0 chnl=15
char id=65 x=500 y=5 width=160 height=198 xoffset=0 yoffset=-83 xadvance=160 page=0 chnl=15
char id=65 x=665 y=5 width=160 height=198 xoffset=0 yoffset=-83 xadvance=160 page=0 chnl=15
char id=65 x=830 y=5 width=160 height=198 xoffset=0 yoffset=-83 xadvance=160 page=0 chnl=15
char id=65 x=5 y=208 width=160 height=198 xoffset=0 yoffset=-83 xadvance=160 page=0 chnl=15
char id=65 x=170 y=208 width=160 height=198 xoffset=0 yoffset=-83 xadvance=160 page=0 chnl=15
char id=65 x=335 y=208 width=160 height=198 xoffset=0 yoffset=-83 xadvance=160 page=0 chnl=15
char id=65 x=500 y=208 width=160 height=198 xoffset=0 yoffset=-83 xadvance=160 page=0 chnl=15

View File

@@ -0,0 +1,33 @@
{
"ver": "1.0.6",
"importer": "bitmap-font",
"imported": true,
"uuid": "2988f0d5-9eaa-4296-95e4-c1ab6cdd8d6c",
"files": [
".json"
],
"subMetas": {},
"userData": {
"_fntConfig": {
"commonHeight": 32,
"fontSize": 32,
"atlasName": "Ifont0.png",
"fontDefDictionary": {
"65": {
"rect": {
"x": 500,
"y": 208,
"width": 160,
"height": 198
},
"xOffset": 0,
"yOffset": -83,
"xAdvance": 160
}
},
"kerningDict": {}
},
"fontSize": 32,
"textureUuid": "c3f96bca-d003-4aa8-8771-ab547a9ce817"
}
}

View File

@@ -0,0 +1,20 @@
<?xml version="1.0"?>
<font>
<info face="Arial" size="32" bold="0" italic="0" charset="" unicode="1" stretchH="100" smooth="1" aa="1" padding="0,0,0,0" spacing="1,1" outline="0"/>
<common lineHeight="32" base="26" scaleW="995" scaleH="411" pages="1" packed="0" alphaChnl="1" redChnl="0" greenChnl="0" blueChnl="0"/>
<pages>
<page id="0" file="Ifont0.png"/>
</pages>
<chars count="10">
<char id="65" x="5" y="5" width="160" height="198" xoffset="0" yoffset="-83" xadvance="160" page="0" chnl="15"/>
<char id="65" x="170" y="5" width="160" height="198" xoffset="0" yoffset="-83" xadvance="160" page="0" chnl="15"/>
<char id="65" x="335" y="5" width="160" height="198" xoffset="0" yoffset="-83" xadvance="160" page="0" chnl="15"/>
<char id="65" x="500" y="5" width="160" height="198" xoffset="0" yoffset="-83" xadvance="160" page="0" chnl="15"/>
<char id="65" x="665" y="5" width="160" height="198" xoffset="0" yoffset="-83" xadvance="160" page="0" chnl="15"/>
<char id="65" x="830" y="5" width="160" height="198" xoffset="0" yoffset="-83" xadvance="160" page="0" chnl="15"/>
<char id="65" x="5" y="208" width="160" height="198" xoffset="0" yoffset="-83" xadvance="160" page="0" chnl="15"/>
<char id="65" x="170" y="208" width="160" height="198" xoffset="0" yoffset="-83" xadvance="160" page="0" chnl="15"/>
<char id="65" x="335" y="208" width="160" height="198" xoffset="0" yoffset="-83" xadvance="160" page="0" chnl="15"/>
<char id="65" x="500" y="208" width="160" height="198" xoffset="0" yoffset="-83" xadvance="160" page="0" chnl="15"/>
</chars>
</font>

View File

@@ -0,0 +1,33 @@
{
"ver": "1.0.6",
"importer": "bitmap-font",
"imported": true,
"uuid": "d82c9fb1-aaa2-4fa0-8176-c877507b2f3d",
"files": [
".json"
],
"subMetas": {},
"userData": {
"_fntConfig": {
"commonHeight": 32,
"fontSize": 32,
"atlasName": "Ifont0.png",
"fontDefDictionary": {
"65": {
"rect": {
"x": 500,
"y": 208,
"width": 160,
"height": 198
},
"xOffset": 0,
"yOffset": -83,
"xAdvance": 160
}
},
"kerningDict": {}
},
"fontSize": 32,
"textureUuid": "c3f96bca-d003-4aa8-8771-ab547a9ce817"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

View File

@@ -0,0 +1,134 @@
{
"ver": "1.0.27",
"importer": "image",
"imported": true,
"uuid": "c3f96bca-d003-4aa8-8771-ab547a9ce817",
"files": [
".json",
".png"
],
"subMetas": {
"6c48a": {
"importer": "texture",
"uuid": "c3f96bca-d003-4aa8-8771-ab547a9ce817@6c48a",
"displayName": "Ifont0",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "clamp-to-edge",
"wrapModeT": "clamp-to-edge",
"imageUuidOrDatabaseUri": "c3f96bca-d003-4aa8-8771-ab547a9ce817",
"isUuid": true,
"visible": false,
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
},
"f9941": {
"importer": "sprite-frame",
"uuid": "c3f96bca-d003-4aa8-8771-ab547a9ce817@f9941",
"displayName": "Ifont0",
"id": "f9941",
"name": "spriteFrame",
"userData": {
"trimThreshold": 1,
"rotated": false,
"offsetX": -4,
"offsetY": -0.5,
"trimX": 7,
"trimY": 7,
"width": 973,
"height": 398,
"rawWidth": 995,
"rawHeight": 411,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"packable": true,
"pixelsToUnit": 100,
"pivotX": 0.5,
"pivotY": 0.5,
"meshType": 0,
"vertices": {
"rawPosition": [
-486.5,
-199,
0,
486.5,
-199,
0,
-486.5,
199,
0,
486.5,
199,
0
],
"indexes": [
0,
1,
2,
2,
1,
3
],
"uv": [
7,
404,
980,
404,
7,
6,
980,
6
],
"nuv": [
0.007035175879396985,
0.014598540145985401,
0.9849246231155779,
0.014598540145985401,
0.007035175879396985,
0.9829683698296837,
0.9849246231155779,
0.9829683698296837
],
"minPos": [
-486.5,
-199,
0
],
"maxPos": [
486.5,
199,
0
]
},
"isUuid": true,
"imageUuidOrDatabaseUri": "c3f96bca-d003-4aa8-8771-ab547a9ce817@6c48a",
"atlasUuid": "",
"trimType": "auto"
},
"ver": "1.0.12",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "sprite-frame",
"hasAlpha": true,
"fixAlphaTransparencyArtifacts": false,
"redirect": "c3f96bca-d003-4aa8-8771-ab547a9ce817@6c48a"
}
}

View File

@@ -13,6 +13,7 @@ import { HeroInfo, HType } from "../common/config/heroSet";
import { HeroViewComp } from "../hero/HeroViewComp";
import { FacSet } from "../common/config/GameSet";
import { MoveComp } from "../hero/MoveComp";
import { MissionHeroCompComp } from "./MissionHeroComp";
const { ccclass, property } = _decorator;
@@ -231,6 +232,13 @@ export class MissionCardComp extends CCComp {
this.syncMissionHeroData(current);
const heroMax = this.getMissionHeroMaxNum();
if (current >= heroMax) {
const heroUuid = Number(payload?.uuid ?? 0);
const heroLv = Math.max(1, Math.floor(Number(payload?.hero_lv ?? 1)));
if (this.canUseHeroCardByMerge(heroUuid, heroLv)) {
payload.cancel = false;
payload.reason = "";
return;
}
payload.cancel = true;
payload.reason = "hero_limit";
oops.gui.toast(`英雄已满 (${current}/${heroMax})`);
@@ -238,6 +246,39 @@ export class MissionCardComp extends CCComp {
}
}
private canUseHeroCardByMerge(heroUuid: number, heroLv: number): boolean {
if (!heroUuid) return false;
const mergeRule = this.getMergeRule();
if (heroLv >= mergeRule.maxLv) return false;
const sameCount = this.countAliveHeroesByUuidAndLv(heroUuid, heroLv);
return sameCount + 1 >= mergeRule.needCount;
}
private countAliveHeroesByUuidAndLv(heroUuid: number, heroLv: number): number {
let count = 0;
const actors = this.queryAliveHeroActors();
for (let i = 0; i < actors.length; i++) {
const model = actors[i].model;
if (!model) continue;
if (model.hero_uuid !== heroUuid) continue;
if (model.lv !== heroLv) continue;
count += 1;
}
return count;
}
private getMergeRule(): { needCount: number, maxLv: number } {
let needCount = 2;
let maxLv = 3;
ecs.query(ecs.allOf(MissionHeroCompComp)).forEach((entity: ecs.Entity) => {
const comp = entity.get(MissionHeroCompComp);
if (!comp) return;
needCount = comp.merge_need_count === 2 ? 2 : 3;
maxLv = Math.max(1, Math.floor(comp.merge_max_lv ?? 3));
});
return { needCount, maxLv };
}
private onUseSpecialCard(event: string, args: any) {
const payload = args ?? event;
const uuid = Number(payload?.uuid ?? 0);