feat(技能): 优化治疗技能的目标选择逻辑

将治疗技能的目标选择从随机选择后按血量排序改为优先选择缺失生命值最多的目标,提升治疗效率
This commit is contained in:
walkpan
2026-04-04 08:54:19 +08:00
parent 07b8d47760
commit a14115fb6a
4 changed files with 392 additions and 151 deletions

View File

@@ -29,34 +29,31 @@
},
{
"__id__": 37
},
{
"__id__": 45
}
],
"_active": true,
"_components": [
{
"__id__": 45
},
{
"__id__": 47
},
{
"__id__": 49
},
{
"__id__": 51
},
{
"__id__": 53
},
{
"__id__": 55
},
{
"__id__": 57
},
{
"__id__": 59
},
{
"__id__": 61
},
{
"__id__": 63
}
],
"_prefab": {
"__id__": 65
"__id__": 57
},
"_lpos": {
"__type__": "cc.Vec3",
@@ -654,10 +651,10 @@
"__id__": 37
},
"asset": {
"__uuid__": "a848a83a-fe5a-4fe8-9db4-4009f8445b88",
"__uuid__": "02e38f62-860e-4bb9-86d9-a59f073e2881",
"__expectedType__": "cc.Prefab"
},
"fileId": "c46/YsCPVOJYA4mWEpNYRx",
"fileId": "54R/aYBglLI4Jn5pm++Jx8",
"instance": {
"__id__": 39
},
@@ -665,7 +662,7 @@
},
{
"__type__": "cc.PrefabInstance",
"fileId": "029JdsuvdNkrqL7gx96ZPl",
"fileId": "83JAqLl/ZNzJIv+L012Q2q",
"prefabRootNode": {
"__id__": 1
},
@@ -695,119 +692,7 @@
"propertyPath": [
"_name"
],
"value": "buff_dian"
},
{
"__type__": "cc.TargetInfo",
"localID": [
"c46/YsCPVOJYA4mWEpNYRx"
]
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 41
},
"propertyPath": [
"_lpos"
],
"value": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
}
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 41
},
"propertyPath": [
"_lrot"
],
"value": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
}
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 41
},
"propertyPath": [
"_euler"
],
"value": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
}
},
{
"__type__": "cc.Node",
"_objFlags": 0,
"_parent": {
"__id__": 1
},
"_prefab": {
"__id__": 46
},
"__editorExtras__": {}
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 45
},
"asset": {
"__uuid__": "7e41bd15-2cf8-471c-9e13-372d5ae3d0ba",
"__expectedType__": "cc.Prefab"
},
"fileId": "54R/aYBglLI4Jn5pm++Jx8",
"instance": {
"__id__": 47
},
"targetOverrides": null
},
{
"__type__": "cc.PrefabInstance",
"fileId": "ddO5Iw9GxGwIP6dvH8i3Zg",
"prefabRootNode": {
"__id__": 1
},
"mountedChildren": [],
"mountedComponents": [],
"propertyOverrides": [
{
"__id__": 48
},
{
"__id__": 50
},
{
"__id__": 51
},
{
"__id__": 52
}
],
"removedComponents": []
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 49
},
"propertyPath": [
"_name"
],
"value": "maxw"
"value": "plus"
},
{
"__type__": "cc.TargetInfo",
@@ -818,7 +703,7 @@
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 49
"__id__": 41
},
"propertyPath": [
"_lpos"
@@ -833,7 +718,7 @@
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 49
"__id__": 41
},
"propertyPath": [
"_lrot"
@@ -849,7 +734,7 @@
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 49
"__id__": 41
},
"propertyPath": [
"_euler"
@@ -871,7 +756,7 @@
},
"_enabled": true,
"__prefab": {
"__id__": 54
"__id__": 46
},
"_contentSize": {
"__type__": "cc.Size",
@@ -899,7 +784,7 @@
},
"_enabled": true,
"__prefab": {
"__id__": 56
"__id__": 48
},
"anm": {
"__id__": 5
@@ -920,7 +805,7 @@
},
"_enabled": true,
"__prefab": {
"__id__": 58
"__id__": 50
},
"debugMode": false,
"_id": ""
@@ -939,7 +824,7 @@
},
"_enabled": true,
"__prefab": {
"__id__": 60
"__id__": 52
},
"enabledContactListener": true,
"bullet": false,
@@ -973,7 +858,7 @@
},
"_enabled": true,
"__prefab": {
"__id__": 62
"__id__": 54
},
"tag": 0,
"_group": 4,
@@ -1007,7 +892,7 @@
},
"_enabled": true,
"__prefab": {
"__id__": 64
"__id__": 56
},
"playOnLoad": false,
"_clips": [],
@@ -1030,9 +915,6 @@
"instance": null,
"targetOverrides": null,
"nestedPrefabInstanceRoots": [
{
"__id__": 45
},
{
"__id__": 37
},

View File

@@ -0,0 +1,338 @@
[
{
"__type__": "cc.Prefab",
"_name": "plus",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "plus",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [
{
"__id__": 2
},
{
"__id__": 10
}
],
"_active": true,
"_components": [
{
"__id__": 18
}
],
"_prefab": {
"__id__": 20
},
"_lpos": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_lrot": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_lscale": {
"__type__": "cc.Vec3",
"x": 1,
"y": 1,
"z": 1
},
"_mobility": 0,
"_layer": 1,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.Node",
"_objFlags": 0,
"_parent": {
"__id__": 1
},
"_prefab": {
"__id__": 3
},
"__editorExtras__": {}
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 2
},
"asset": {
"__uuid__": "7e41bd15-2cf8-471c-9e13-372d5ae3d0ba",
"__expectedType__": "cc.Prefab"
},
"fileId": "54R/aYBglLI4Jn5pm++Jx8",
"instance": {
"__id__": 4
},
"targetOverrides": null
},
{
"__type__": "cc.PrefabInstance",
"fileId": "73Bl2rptBKGr6i8cMQId1k",
"prefabRootNode": {
"__id__": 1
},
"mountedChildren": [],
"mountedComponents": [],
"propertyOverrides": [
{
"__id__": 5
},
{
"__id__": 7
},
{
"__id__": 8
},
{
"__id__": 9
}
],
"removedComponents": []
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 6
},
"propertyPath": [
"_name"
],
"value": "maxw"
},
{
"__type__": "cc.TargetInfo",
"localID": [
"54R/aYBglLI4Jn5pm++Jx8"
]
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 6
},
"propertyPath": [
"_lpos"
],
"value": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
}
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 6
},
"propertyPath": [
"_lrot"
],
"value": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
}
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 6
},
"propertyPath": [
"_euler"
],
"value": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
}
},
{
"__type__": "cc.Node",
"_objFlags": 0,
"_parent": {
"__id__": 1
},
"_prefab": {
"__id__": 11
},
"__editorExtras__": {}
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 10
},
"asset": {
"__uuid__": "a848a83a-fe5a-4fe8-9db4-4009f8445b88",
"__expectedType__": "cc.Prefab"
},
"fileId": "c46/YsCPVOJYA4mWEpNYRx",
"instance": {
"__id__": 12
},
"targetOverrides": null
},
{
"__type__": "cc.PrefabInstance",
"fileId": "7fFzhENiBDf5TeBL7e/kJ+",
"prefabRootNode": {
"__id__": 1
},
"mountedChildren": [],
"mountedComponents": [],
"propertyOverrides": [
{
"__id__": 13
},
{
"__id__": 15
},
{
"__id__": 16
},
{
"__id__": 17
}
],
"removedComponents": []
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 14
},
"propertyPath": [
"_name"
],
"value": "buff_dian"
},
{
"__type__": "cc.TargetInfo",
"localID": [
"c46/YsCPVOJYA4mWEpNYRx"
]
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 14
},
"propertyPath": [
"_lpos"
],
"value": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
}
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 14
},
"propertyPath": [
"_lrot"
],
"value": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
}
},
{
"__type__": "CCPropertyOverrideInfo",
"targetInfo": {
"__id__": 14
},
"propertyPath": [
"_euler"
],
"value": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
}
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 19
},
"_contentSize": {
"__type__": "cc.Size",
"width": 100,
"height": 100
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "77z0467LpD9JrxJ4yirYik"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "54R/aYBglLI4Jn5pm++Jx8",
"instance": null,
"targetOverrides": null,
"nestedPrefabInstanceRoots": [
{
"__id__": 10
},
{
"__id__": 2
}
]
}
]

View File

@@ -0,0 +1,13 @@
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "02e38f62-860e-4bb9-86d9-a59f073e2881",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "plus"
}
}

View File

@@ -206,8 +206,9 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
const sUp = SkillUpList[_s_uuid] ?? SkillUpList[1001];
const sAp =config.ap+sUp.ap*_skillLv;
const sHit=config.hit_count+sUp.hit_count*_skillLv;
const selectedTargets = this.pickRandomFriendlyTargets(targets, sHit);
const applyTargets = kind === SkillKind.Heal ? this.sortTargetsByLowestHp(selectedTargets) : selectedTargets;
const applyTargets = kind === SkillKind.Heal
? this.pickHealTargetsByMostMissingHp(targets, sHit)
: this.pickRandomFriendlyTargets(targets, sHit);
for (const target of applyTargets) {
if (!target.ent) continue;
const model = target.ent.get(HeroAttrsComp);
@@ -254,16 +255,23 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
return selected;
}
private sortTargetsByLowestHp(targets: HeroViewComp[]): HeroViewComp[] {
private pickHealTargetsByMostMissingHp(targets: HeroViewComp[], hitCount: number): HeroViewComp[] {
if (!targets || targets.length === 0) return [];
const validHitCount = Math.max(1, Math.floor(hitCount));
const sortedTargets = this.sortTargetsByMostMissingHp(targets);
return sortedTargets.slice(0, Math.min(validHitCount, sortedTargets.length));
}
private sortTargetsByMostMissingHp(targets: HeroViewComp[]): HeroViewComp[] {
return [...targets].sort((a, b) => {
const aModel = a.ent?.get(HeroAttrsComp);
const bModel = b.ent?.get(HeroAttrsComp);
const aMissingHp = aModel && aModel.hp_max > 0 ? Math.max(0, aModel.hp_max - aModel.hp) : -1;
const bMissingHp = bModel && bModel.hp_max > 0 ? Math.max(0, bModel.hp_max - bModel.hp) : -1;
if (aMissingHp !== bMissingHp) return bMissingHp - aMissingHp;
const aRatio = aModel && aModel.hp_max > 0 ? aModel.hp / aModel.hp_max : 1;
const bRatio = bModel && bModel.hp_max > 0 ? bModel.hp / bModel.hp_max : 1;
if (aRatio !== bRatio) return aRatio - bRatio;
const aHp = aModel?.hp ?? Number.MAX_SAFE_INTEGER;
const bHp = bModel?.hp ?? Number.MAX_SAFE_INTEGER;
return aHp - bHp;
return aRatio - bRatio;
});
}