Compare commits

...

2 Commits

Author SHA1 Message Date
Putoo
732ff93b16 Merge remote-tracking branch 'master/master' 2026-07-04 18:07:47 +08:00
Putoo
fa00fc5d66 12121 2026-07-04 18:07:37 +08:00
26 changed files with 871 additions and 69 deletions

View File

@@ -13,5 +13,6 @@
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASqlSugarScopeProvider_002Ecs_002Fl_003AC_0021_003FUsers_003F29055_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6c0f22f0a47643a3b2a40899acd2044c2e3a00_003Fc5_003F4738d33f_003FSqlSugarScopeProvider_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AStringAssist_002Ecs_002Fl_003AC_0021_003FUsers_003F29055_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fa380d649d5b2495d9bfa0fa24f13662b6400_003Fee_003F90da4dea_003FStringAssist_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AString_002Ecs_002Fl_003AC_0021_003FUsers_003F29055_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F51505665371d472f8bdbc333fa4d888cf49938_003Fdf_003F23ca03dd_003FString_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATask_002Ecs_002Fl_003AC_0021_003FUsers_003F29055_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F51505665371d472f8bdbc333fa4d888cf49938_003F14_003Fa1e9b3d3_003FTask_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATimeAssist_002Ecs_002Fl_003AC_0021_003FUsers_003F29055_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fa380d649d5b2495d9bfa0fa24f13662b6400_003Fe6_003F9539602d_003FTimeAssist_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATokenValidationParameters_002Ecs_002Fl_003AC_0021_003FUsers_003F29055_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Ffbb48859ccd84b0d884ab212a4cf9fdb5f820_003F55_003F417754e1_003FTokenValidationParameters_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>

View File

@@ -0,0 +1,12 @@
namespace Application.Domain.Entity;
public class FightResultModel
{
public int result { get; set; }
public int myHarm { get; set; }
public int otHarm { get; set; }
public List<string> myStateData { get; set; }
public List<dynamic> myRemData { get; set; }
public List<string> otStateData { get; set; }
public List<dynamic> otRemData { get; set; }
}

View File

@@ -4,7 +4,8 @@ public static class UserEnum
{
public enum AttrCode
{
Person
Person,
Monster
}
public enum ConfigCode

View File

@@ -9,9 +9,8 @@ public interface IGameFightService
#endregion
#region
Task<game_fight_data> GetFightInfo(string fightId);
Task<long> GetFightBlood(string keyId, long maxBlood);
Task SetFightBlood(string keyId, long blood);
Task AddFightHarm(string fightId, string userId, long harm);
Task RemoveFightHarm(string fightId, string userId);
Task<bool> AddFight(string fightId, string areaCode, string keyId, string mainId, string code,
string scene, string mapId,
string userId, long exp = 0, long copper = 0, long petExp = 0, string award = "", string pars = "");

View File

@@ -16,5 +16,13 @@ public interface IGameMonsterService
Task<unit_user_monster> GetCreateMonsterInfo(string umId);
Task<List<MapMonsterModel>> GetMapMonster(string userId, string mapId, string teamId);
#endregion
#region
Task<UserAttrModel> GetMonsterAttrModel(string keyId, string monsterId);
Task SetMonsterBlood(string keyId, int blood);
#endregion
}

View File

@@ -54,28 +54,6 @@ public class GameFightService(ISqlSugarClient DbClient, IRedisCache redis) : IGa
return data;
}
public async Task<long> GetFightBlood(string keyId, long maxBlood)
{
long blood = maxBlood;
string key = string.Format(FightCache.FightCacheKeys, "FightData:Blood", keyId);
if (await redis.ExistsAsync(key))
{
blood = await redis.GetAsync<long>(key);
blood = blood > maxBlood ? maxBlood : blood;
}
else
{
await SetFightBlood(keyId, blood);
}
return blood;
}
public async Task SetFightBlood(string keyId, long blood)
{
string key = string.Format(FightCache.FightCacheKeys, "FightData:Blood", keyId);
await redis.SetAsync(key, blood, 43200);
}
public async Task AddFightHarm(string fightId,string userId, long harm)
{
@@ -91,6 +69,12 @@ public class GameFightService(ISqlSugarClient DbClient, IRedisCache redis) : IGa
await redis.AddHashAsync(key, userId, harm);
}
}
public async Task RemoveFightHarm(string fightId,string userId)
{
string key = string.Format(FightCache.FightCacheKeys, "FightData:Harm", fightId);
await redis.DelHashAsync(key, userId);
}
private async Task ClearFightInfoCache(string fightId, string keyId)

View File

@@ -204,4 +204,66 @@ public class GameMonsterService(ISqlSugarClient DbClient, IRedisCache redis) : I
}
#endregion
#region
public async Task<UserAttrModel> GetMonsterAttrModel(string keyId,string monsterId)
{
UserAttrModel temp = new UserAttrModel();
var monsterInfo = await GetMonsterInfo(monsterId);
if (monsterInfo != null)
{
temp.id = keyId;
temp.viceId = monsterId;
temp.name = monsterInfo.name;
temp.IsSystem = 1;
temp.isCopy = (int)monsterInfo.isCopy;
temp.sex = "Default";
temp.code = nameof(UserEnum.AttrCode.Monster);
temp.lev = (int)monsterInfo.lev;
temp.minAtk = (int)monsterInfo.minAtk;
temp.maxAtk = (int)monsterInfo.maxAtk;
temp.defense = (int)monsterInfo.defense;
temp.agility = (int)monsterInfo.agility;
temp.upBlood = (int)monsterInfo.blood;
temp.upMorale = 1;
temp.morale = 0;
temp = GameAttrTool.GetRoleAttrTempMerge(temp, monsterInfo.attr);
temp.score = 0;
//处理负面
var attrService = App.GetService<IUnitUserAttrService>();
var loadState = await attrService.GetUserLoadState(keyId);
temp = await GameAttrTool.CheckRoleLoadBuff(temp, loadState);
temp.blood = await GetMonsterBlood(keyId, temp.upBlood);
}
return temp;
}
private async Task<int> GetMonsterBlood(string keyId, int maxBlood)
{
int blood = maxBlood;
blood = blood < 0 ? 0 : blood;
string key = string.Format(FightCache.FightCacheKeys, "FightData:Blood", keyId);
if (await redis.ExistsAsync(key))
{
blood = await redis.GetAsync<int>(key);
blood = blood > maxBlood ? maxBlood : blood;
blood = blood < 0 ? 0 : blood;
}
else
{
await SetMonsterBlood(keyId, blood);
}
return blood;
}
public async Task SetMonsterBlood(string keyId, int blood)
{
string key = string.Format(FightCache.FightCacheKeys, "FightData:Blood", keyId);
await redis.SetAsync(key, blood, 43200);
}
#endregion
}

View File

@@ -778,6 +778,7 @@ public class UnitUserAttrService(ISqlSugarClient DbClient, IRedisCache redis) :
{
data.Remove(onData);
onData.count += 1;
onData.count = onData.count > 10 ? 10 : onData.count;
result = await redis.AddHashAsync(key, userId, data);
}

View File

@@ -21,9 +21,9 @@ public class UnitUserWeight(ISqlSugarClient DbClient, IRedisCache redis) : IUnit
{
int result = 100 + (int)data.maxWeight;
var attrService = App.GetService<IUnitUserAttrService>();
int myLev = await attrService.GetUserLev(data.userId);
result += myLev * GameConfig.UpLevAddWeight;
//其他属性加层
var userAttr = await attrService.GetUserAttrModel(data.userId);
result += userAttr.lev * GameConfig.UpLevAddWeight;
result += userAttr.weight;
return result;
}

View File

@@ -227,11 +227,6 @@ public class GameAttrTool
decimal radio = item.count * 0.04M;
temp.defense = Convert.ToInt32(temp.defense * (1.0M - radio));
}
else if (item.code == nameof(GameEnum.AttrCode.PalsyAtk))
{
decimal radio = item.count * 0.1M;
temp.Atk_Next -= radio;
}
}
return temp;

View File

@@ -0,0 +1,11 @@
namespace Application.Domain;
public static class UserStateTool
{
public static async Task<bool> CheckUserFight(string userId)
{
var fightService = App.GetService<IGameFightService>();
var myFight = await fightService.GetUserFight(userId);
return myFight.Count > 0;
}
}

View File

@@ -1,7 +0,0 @@
namespace Application.Service.Pub
{
public class Class1
{
}
}

View File

@@ -27,7 +27,7 @@ public class MapController : ControllerBase
public MapController(IUnitUserService userService, IGameMapService mapService, IGameChatService chatService,
IUnitUserAttrService attrService, IMessageService messageService, IUnitUserWeight weightService,
IUnitUserAccService accService, IGameSkillService skillService, IGameGoodsService goodsService,
IGameTeamService teamService, IGameMonsterService monsterService,IGameFightService fightService)
IGameTeamService teamService, IGameMonsterService monsterService, IGameFightService fightService)
{
_userService = userService;
_mapService = mapService;
@@ -55,6 +55,7 @@ public class MapController : ControllerBase
{
string userId = StateHelper.userId;
int area = StateHelper.areaId;
string gameTips = string.Empty;
game_city_map mapInfo = new game_city_map();
#region
@@ -79,6 +80,7 @@ public class MapController : ControllerBase
//设置默认地图点
await _mapService.SetUserMapDefult(userId);
isSelfMap = true;
gameTips = "➢当前体力为0,恢复一下吧!";
}
}
@@ -145,7 +147,7 @@ public class MapController : ControllerBase
var userFight = await _fightService.GetUserFight(userId);
string fightId = userFight.Count > 0 ? userFight[0] : "";
object ret = new
{
mapInfo,
@@ -159,7 +161,8 @@ public class MapController : ControllerBase
mapRes,
broadcast,
monster = monsterData,
fightId
fightId,
gameTips
};
return PoAction.Ok(ret);

View File

@@ -15,14 +15,19 @@ public class FightController : ControllerBase
private readonly IGameMonsterService _monsterService;
private readonly IUnitUserAttrService _attrService;
private readonly IGameMapService _mapService;
private readonly IUnitUserAccService _accService;
private readonly IGameGoodsService _goodsService;
public FightController(IGameFightService fightService, IGameMonsterService monsterService,
IUnitUserAttrService attrService, IGameMapService mapService)
IUnitUserAttrService attrService, IGameMapService mapService, IUnitUserAccService accService,
IGameGoodsService goodsService)
{
_fightService = fightService;
_monsterService = monsterService;
_attrService = attrService;
_mapService = mapService;
_accService = accService;
_goodsService = goodsService;
}
/// <summary>
@@ -68,20 +73,21 @@ public class FightController : ControllerBase
areaCode = monster.areaCode;
pars = JsonConvert.SerializeObject(new { type = "Create", code = monster.code, par = monster.par });
}
var monsterInfo = await _monsterService.GetMonsterInfo(mainId);
if (monsterInfo != null)
{
var userAttr = await _attrService.GetUserAttrModel(userId, scene);
//处理奖励和资源
exp = Convert.ToInt64(monsterInfo.exp * (1.0m + userAttr.addExp)) ;
exp = Convert.ToInt64(monsterInfo.exp * (1.0m + userAttr.addExp));
copper = Convert.ToInt64(monsterInfo.copper * (1.0m + userAttr.addGold));
petExp = (long)monsterInfo.petExp;
if (!string.IsNullOrEmpty(monsterInfo.award))//生成奖励
if (!string.IsNullOrEmpty(monsterInfo.award)) //生成奖励
{
var awardModel = JsonConvert.DeserializeObject<MonsterAwardModel>(monsterInfo.award);
if (awardModel.type == nameof(MonsterEnum.AwardCode.Default))
{
var getAward = GameBus.GetRandomGoods(awardModel.award, 1,userAttr.burst);
var getAward = GameBus.GetRandomGoods(awardModel.award, 1, userAttr.burst);
award = JsonConvert.SerializeObject(new FightAwardModel() { code = "Default", award = getAward });
}
}
@@ -99,9 +105,257 @@ public class FightController : ControllerBase
}
}
/// <summary>
/// 战斗接口
/// </summary>
/// <param name="parms"></param>
/// <returns></returns>
[HttpPost]
public async Task<IPoAction> Fight([FromBody] FightParms parms)
{
return PoAction.Ok(true);
string userId = StateHelper.userId;
string fightId = parms.fightId;
int myHarm = 0;
int otHarm = 0;
var myFight = await _fightService.GetUserFight(userId);
if (myFight.Any(it => it == fightId) == false)
{
return PoAction.Message("战斗不存在!");
}
var fight = await _fightService.GetFightInfo(fightId);
if (fight == null)
{
await _fightService.RemoveUserFight(userId, fightId);
return PoAction.Message("战斗不存在!");
}
if (fight.state == 1)
{
await _fightService.RemoveUserFight(userId, fightId);
return PoAction.Message("战斗结束", 100);
}
#region
FightResultModel fightResult = new FightResultModel()
{
result = -1
};
if (!string.IsNullOrEmpty(parms.data))
{
fightResult = JsonConvert.DeserializeObject<FightResultModel>(parms.data);
}
#endregion
//更新攻击
if (fightResult.result == 0)
{
myHarm = fightResult.myHarm;
otHarm = fightResult.otHarm;
await _attrService.UpdateUserBlood(userId, 1, fightResult.myHarm);
}
var myAttr = await _attrService.GetUserAttrModel(userId, fight.scene);
UserAttrModel otAttr = new UserAttrModel();
if (fight.code == nameof(GameEnum.FightCode.PVE))
{
otAttr = await _monsterService.GetMonsterAttrModel(fight.keyId, fight.mainId);
if (fightResult.result == 0)
{
otAttr.blood = otAttr.blood + fightResult.otHarm;
otAttr.blood = otAttr.blood < 0 ? 0 : otAttr.blood;
otAttr.blood = otAttr.blood > otAttr.upBlood ? otAttr.upBlood : otAttr.blood;
await _monsterService.SetMonsterBlood(fight.keyId, otAttr.blood);
}
}
else
{
otAttr = await _attrService.GetUserAttrModel(fight.mainId, fight.scene);
if (fightResult.result == 0)
{
await _attrService.UpdateUserBlood(fight.mainId, 1, fightResult.otHarm);
}
}
//结束战斗都此处直接返回
if (otAttr.blood < 1||myAttr.blood<1)
{
await _fightService.RemoveUserFight(userId, fightId);
return PoAction.Message("战斗结束", 100);
}
//获取个人药品栏
var myDrug = await _attrService.GetUserDrug(userId);
//获取个人负面
var myLoad = await _attrService.GetUserLoadState(userId);
//冷却时间
int cool = 1000;
if (myAttr.agility > otAttr.agility&&otAttr.agility>0)
{
decimal diff = myAttr.agility - otAttr.agility;
decimal bl = diff / otAttr.agility;
cool = Convert.ToInt32(bl * 1000.0m);
cool = cool > 1000 ? 1000 : cool;
}
//麻痹状态增加冷却时间
var atkCoolData = myLoad.Find(it => it.code == nameof(GameEnum.AttrCode.PalsyAtk));
if (atkCoolData != null)
{
cool = Convert.ToInt32(cool * (1 + atkCoolData.count * 0.1M));
}
//更新伤害提示
int exitCopper = otAttr.lev * 5;
var result = new
{
myHarm,
otHarm,
myAttr = myAttr,
otAttr = otAttr,
myDrug = myDrug.drug,
myLoad = myLoad,
exitCopper,
cool,
};
return PoAction.Ok(result);
}
/// <summary>
/// 退出战斗
/// </summary>
/// <param name="fightId"></param>
/// <returns></returns>
[HttpGet]
public async Task<IPoAction> Exit(string fightId)
{
string userId = StateHelper.userId;
var myFight = await _fightService.GetUserFight(userId);
if (myFight.Any(it => it == fightId) == false)
{
return PoAction.Message("战斗不存在!");
}
var fight = await _fightService.GetFightInfo(fightId);
if (fight == null)
{
await _fightService.RemoveUserFight(userId, fightId);
return PoAction.Message("战斗不存在!");
}
if (fight.state == 1)
{
await _fightService.RemoveUserFight(userId, fightId);
return PoAction.Message("战斗结束", 100);
}
UserAttrModel otAttr = new UserAttrModel();
if (fight.code == nameof(GameEnum.FightCode.PVE))
{
otAttr = await _monsterService.GetMonsterAttrModel(fight.keyId, fight.mainId);
}
else
{
otAttr = await _attrService.GetUserAttrModel(fight.mainId, fight.scene);
}
int needCopper = otAttr.lev * 5;
var myAcc = await _accService.GetUserAccInfo(userId, nameof(AccEnum.AccType.copper));
if (myAcc < needCopper)
{
return PoAction.Message("铜贝不足!", 101);
}
if (await _accService.UpdateUserCopper(userId, 0, needCopper, "退出战斗"))
{
if (await _fightService.RemoveUserFight(userId, fightId))
{
await _fightService.RemoveFightHarm(fightId, userId); //移除伤害
var nextFight = myFight.FindAll(it => it != fightId);
string nextId = nextFight.Count > 0 ? nextFight[0] : "";
return PoAction.Ok(nextId);
}
else
{
return PoAction.Message("退出失败,请稍后尝试!", 101);
}
}
else
{
return PoAction.Message("退出失败,请稍后尝试!", 101);
}
}
/// <summary>
/// 使用药品
/// </summary>
/// <param name="fightId"></param>
/// <param name="drugId"></param>
/// <returns></returns>
[HttpGet]
public async Task<IPoAction> UseFightDrug(string fightId, string drugId)
{
string userId = StateHelper.userId;
var myFight = await _fightService.GetUserFight(userId);
if (myFight.Any(it => it == fightId) == false)
{
return PoAction.Message("战斗不存在!");
}
var fight = await _fightService.GetFightInfo(fightId);
if (fight == null)
{
await _fightService.RemoveUserFight(userId, fightId);
return PoAction.Message("战斗不存在!");
}
if (fight.state == 1)
{
await _fightService.RemoveUserFight(userId, fightId);
return PoAction.Message("战斗结束!");
}
var myDrug = await _attrService.GetUserDrug(userId);
var onDrug = myDrug.drug.Find(it => it.id == drugId);
if (onDrug == null)
{
return PoAction.Message("药品不存在!");
}
if (onDrug.count < 1)
{
return PoAction.Message("药品不足!");
}
var drugConfig = await _goodsService.GetGoodsContent(onDrug.goodsId);
string check = await _goodsService.CheckUseDrug(userId, onDrug.goodsId, drugConfig, fightId);
if (!string.IsNullOrEmpty(check))
{
return PoAction.Message(check);
}
foreach (var item in myDrug.drug)
{
if (item.id == drugId)
{
item.count = item.count - 1;
break;
}
}
if (await _attrService.UpdateUserDrug(myDrug))
{
await _goodsService.UseDrug(userId, onDrug.goodsId, drugConfig, fightId);
return PoAction.Ok("药品使用成功!");
}
else
{
return PoAction.Message("药品使用失败!");
}
}
}

View File

@@ -102,6 +102,11 @@ public class GoodsController : ControllerBase
if (goodsInfo.code == nameof(GoodsEnum.Code.Drug))
{
if (await UserStateTool.CheckUserFight(userId))
{
return PoAction.Message($"战斗状态下无法使用!");
}
var ck = await _goodsService.CheckUseDrug(userId, goodsId, goodsInfo.content);
if (!string.IsNullOrEmpty(ck))
{

View File

@@ -14,13 +14,15 @@ namespace Application.Web.Controllers.Pub
private readonly INoticeService _noticeService;
private readonly IGameAccountService _accountService;
private readonly IUnitUserService _userService;
private readonly IGameMonsterService _monsterService;
public PubController(IAreaService areaService, INoticeService noticeService, IGameAccountService accountService,IUnitUserService userService)
public PubController(IAreaService areaService, INoticeService noticeService, IGameAccountService accountService,IUnitUserService userService,IGameMonsterService monsterService)
{
_areaService = areaService;
_noticeService = noticeService;
_accountService = accountService;
_userService = userService;
_monsterService = monsterService;
}
/// <summary>
@@ -134,5 +136,21 @@ namespace Application.Web.Controllers.Pub
return PoAction.Ok(areaInfo);
}
/// <summary>
/// 怪物信息
/// </summary>
/// <param name="monsterId"></param>
/// <returns></returns>
[HttpGet]
public async Task<IPoAction> GetMonsterInfo(string monsterId)
{
var monster = await _monsterService.GetMonsterInfo(monsterId);
if (monster == null)
{
return PoAction.Message("怪物不存在!");
}
return PoAction.Ok(monster);
}
}
}

View File

@@ -3,4 +3,5 @@
public class FightParms
{
public string fightId { get; set; }
public string data { get; set; }
}

View File

@@ -0,0 +1,9 @@
export interface IFightData<T = any> {
result:number,
myHarm:number,
otHarm:number
myStateData:Array<string>,
myRemData:Array<any>,
otStateData:Array<string>,
otRemData:Array<any>
}

View File

@@ -0,0 +1,48 @@
export interface IUserAttr<T = any> {
id:string,
area:number,
isSystem:number,
isCopy:number,
viceId:string,
name:string,
sex:string,
code:string,
tips:string,
lev:number,
minAtk:number,
maxAtk:number,
defense:number,
agility:number,
blood:number,
upBlood:number,
morale:number,
upMorale:number,
score:number,
inBlood:number,
crit:number,
noHarm:number,
dodge:number,
rebound:number,
reboundLess:number,
punish:number,
slow:number,
slowLess:number,
poison:number,
poisonLess:number,
curse:number,
curseLess:number,
weaken:number,
weakenLess:number,
deadly:number,
deadlyLess:number,
depressed:number,
depressedLess:number,
breach:number,
breachLess:number,
del_Fashion:number,
atk_Next:number,
harm_Add:number,
palsyAtk:number,
palsyAtkLess:number,
}

View File

@@ -0,0 +1,165 @@
<template>
<div class="content">
<div class="common">
<Abutton>{{ autoFight == 0 ? "开启自动攻击" : "关闭自动攻击" }}</Abutton>
</div>
<div class="common">
你向{{ otAttr.name }}发起了攻击!
</div>
<div class="common">
<Abutton @click="FightAtk">攻击</Abutton>
<span>&nbsp;.&nbsp;</span>
<span v-if="otAttr.code == 'Monster'">
<Abar :href='"/prop/monster?m=" + otAttr.viceId'>查看</Abar>
</span>
<span v-else>
<Abar :href='"/user/user?no=" + otAttr.viceId'>查看</Abar>
</span>
<span>&nbsp;.&nbsp;</span>
<Abutton @click="ExitFight">撤退({{ exitCopper }}铜贝)</Abutton>
</div>
<div class="common">
<div>
{{ otAttr.name }}体力({{ otAttr.blood }}/{{ otAttr.upBlood }})
<span v-if="otHarm != 0">
{{ otHarm > 0 ? "+" + otHarm : otHarm }}
</span>
</div>
<div>
你体力({{ myAttr.blood }}/{{ myAttr.upBlood }})
<span v-if="myHarm != 0">
{{ myHarm > 0 ? "+" + myHarm : myHarm }}
</span>
</div>
</div>
<div class="common">
你状态
<span v-for="item in myLoad">
{{ item.name }}({{ item.count }})
</span>
</div>
<div class="common">
<span v-for="(item, index) in myDrug" :key="index">
<Abutton @click="UseFightDrug(item.id)">{{ item.name }}({{ item.count }})</Abutton>
<span v-if="(index + 1) != myDrug.length">&nbsp;.&nbsp;</span>
</span>
</div>
<div class="common">
<Abar href="/user/equ">状态</Abar>
<span>&nbsp;.&nbsp;</span>
<Abar href="/user/bag">物品</Abar>
<span>&nbsp;.&nbsp;</span>
<Abar href="/pet">宠物</Abar>
</div>
</div>
</template>
<script setup lang="ts">
definePageMeta({
layout: layout.empty,
middleware: 'page-loading'
})
let fightId = PageExtend.QueryString("f");
const autoFight = ref(0);
const myHarm = ref(0);
const otHarm = ref(0);
const myAttr = ref<IUserAttr | any>({} as IUserAttr);
const otAttr = ref<IUserAttr | any>({} as IUserAttr);
const myDrug = ref<Array<any>>([]);
const myLoad = ref<Array<any>>([]);
const exitCopper = ref(0);
const coolTime = ref(0);
let coolLock = false;//冷却锁
const coolTimer = ref(0);//冷却定时器
let dataLock = false;//数据锁
onMounted(async () => {
try {
await BindData("");
}
finally {
PageLoading.Close();
}
})
onUnmounted(() => {
clearTimeout(coolTimer.value)
})
/**加载方法 */
const BindData = async (data: string): Promise<void> => {
let result = await FightService.Fight(fightId, data);
if (result.code == 0) {
myAttr.value = result.data.myAttr as IUserAttr;
otAttr.value = result.data.otAttr as IUserAttr;
myDrug.value = result.data.myDrug;
myLoad.value = result.data.myLoad;
exitCopper.value = result.data.exitCopper;
coolTime.value = result.data.cool;
dataLock = false;
myHarm.value = result.data.myHarm;
otHarm.value = result.data.otHarm;
}
else if (result.code == 100) {
PageExtend.RedirectTo("/fight/result?f=" + fightId);
}
else {
PageExtend.RedirectTo("/map");
}
};
/**退出战斗 */
const ExitFight = async () => {
MessageExtend.LoadingToast("退出战斗中...");
let result = await FightService.Exit(fightId);
MessageExtend.LoadingClose();
if (result.code == 0) {
if (result.data == "") {
PageExtend.RedirectTo("/map");
}
else {
PageExtend.RedirectTo("/fight?f=" + result.data);
}
}
else if (result.code == 100) {
PageExtend.RedirectTo("/fight/result?f=" + fightId);
}
else if (result.code == 101) {
MessageExtend.Notify(result.msg, "danger");
}
else {
PageExtend.RedirectTo("/map");
}
}
/**使用药品 */
const UseFightDrug = async (drugId: string) => {
MessageExtend.LoadingToast("药品使用中...");
let result = await FightService.UseFightDrug(fightId, drugId);
MessageExtend.LoadingClose();
if (result.code == 0) {
await BindData("");
}
else {
MessageExtend.Notify(result.msg, "danger");
}
}
/**攻击 */
const FightAtk = async () => {
if (coolLock == false && dataLock == false) {
StartCool();
let result = FightTool.FightHandle(myAttr.value, otAttr.value);
let data = JSON.stringify(result);
await BindData(data);
}
}
const StartCool = () => {
coolLock = true;
dataLock = true;
coolTimer.value = setTimeout(() => {
coolLock = false;
}, coolTime.value)
}
</script>

View File

@@ -0,0 +1 @@
<template></template>

View File

@@ -6,7 +6,9 @@
<Abar href="/task/">任务</Abar>
<Abar href="/user/message/">消息{{ messageCount > 0 ? "(" + messageCount + ")" : "" }}</Abar>
</div>
<div class="content" v-if="gameTips != ''" style="color: red;font-size: 16px;">
{{ gameTips }}
</div>
<div class="notification">
<GameChat :data="chatData" :show-time="0"></GameChat>
</div>
@@ -127,6 +129,7 @@ const mapRes = ref<Array<any>>([]);
const monster = ref<Array<any>>([]);
const messageCount = ref(0);
const broadcast = ref<Array<any>>([]);
const gameTips = ref('');
// 城内地图显示
const showCity = ref(false);
@@ -159,6 +162,7 @@ const BindData = async (map: string): Promise<void> => {
broadcast.value = result.data.broadcast;
MapVent(result.data.mapInfo.near);
onMap.value = mapInfo.value.mapId;
gameTips.value = result.data.gameTips;
console.log(result)
}
else if (result.code == 103) {

View File

@@ -0,0 +1 @@
<template></template>

View File

@@ -12,11 +12,16 @@
<div class="content">
<div class="common" style="">
<Acheak @click="ChangeBag('0')" :on-value="type" on-cheak="0">装备</Acheak>|
<Acheak @click="ChangeBag('1')" :on-value="type" on-cheak="1">药品</Acheak>|
<Acheak @click="ChangeBag('2')" :on-value="type" on-cheak="2"></Acheak>|
<Acheak @click="ChangeBag('3')" :on-value="type" on-cheak="3">坐骑</Acheak>|
<Acheak @click="ChangeBag('4')" :on-value="type" on-cheak="4">九宫</Acheak>|
<Acheak @click="ChangeBag('0')" :on-value="type" on-cheak="0">装备</Acheak>
<span>&nbsp;|&nbsp;</span>
<Acheak @click="ChangeBag('1')" :on-value="type" on-cheak="1"></Acheak>
<span>&nbsp;|&nbsp;</span>
<Acheak @click="ChangeBag('2')" :on-value="type" on-cheak="2">物品</Acheak>
<span>&nbsp;|&nbsp;</span>
<Acheak @click="ChangeBag('3')" :on-value="type" on-cheak="3">坐骑</Acheak>
<span>&nbsp;|&nbsp;</span>
<Acheak @click="ChangeBag('4')" :on-value="type" on-cheak="4">九宫</Acheak>
<span>&nbsp;|&nbsp;</span>
<Acheak @click="ChangeBag('5')" :on-value="type" on-cheak="5">十方</Acheak>
</div>
@@ -29,22 +34,34 @@
</div>
<div class="common">
<div v-if="type == '0'">
<Acheak @click="ChangeChildBag('0')" :on-value="type_ch" on-cheak="0">全部</Acheak>.<Acheak
@click="ChangeChildBag('1')" :on-value="type_ch" on-cheak="1">穿戴</Acheak>.<Acheak
@click="ChangeChildBag('2')" :on-value="type_ch" on-cheak="2">过期</Acheak>.<Acheak
@click="ChangeChildBag('3')" :on-value="type_ch" on-cheak="3">未鉴定</Acheak>
<Acheak @click="ChangeChildBag('0')" :on-value="type_ch" on-cheak="0">全部</Acheak>
<span>&nbsp;.&nbsp;</span>
<Acheak @click="ChangeChildBag('1')" :on-value="type_ch" on-cheak="1">穿戴</Acheak>
<span>&nbsp;.&nbsp;</span>
<Acheak @click="ChangeChildBag('2')" :on-value="type_ch" on-cheak="2">过期</Acheak>
<span>&nbsp;.&nbsp;</span>
<Acheak @click="ChangeChildBag('3')" :on-value="type_ch" on-cheak="3">未鉴定</Acheak>
</div>
<div v-if="type == '2'">
<Acheak @click="ChangeChildBag('0')" :on-value="type_ch" on-cheak="0">全部</Acheak>.<Acheak
@click="ChangeChildBag('1')" :on-value="type_ch" on-cheak="1">宝石</Acheak>.<Acheak
@click="ChangeChildBag('2')" :on-value="type_ch" on-cheak="2">九宫</Acheak>.<Acheak
@click="ChangeChildBag('3')" :on-value="type_ch" on-cheak="3">圣痕</Acheak>.<Acheak
@click="ChangeChildBag('4')" :on-value="type_ch" on-cheak="4">礼包</Acheak>.<Acheak
@click="ChangeChildBag('5')" :on-value="type_ch" on-cheak="5">材料</Acheak>.<Acheak
@click="ChangeChildBag('6')" :on-value="type_ch" on-cheak="6">图纸</Acheak>.<Acheak
@click="ChangeChildBag('7')" :on-value="type_ch" on-cheak="7">卡片</Acheak>.<Acheak
@click="ChangeChildBag('8')" :on-value="type_ch" on-cheak="8">货物</Acheak>.<Acheak
@click="ChangeChildBag('9')" :on-value="type_ch" on-cheak="9">其他</Acheak>
<Acheak @click="ChangeChildBag('0')" :on-value="type_ch" on-cheak="0">全部</Acheak>
<span>&nbsp;.&nbsp;</span>
<Acheak @click="ChangeChildBag('1')" :on-value="type_ch" on-cheak="1">宝石</Acheak>
<span>&nbsp;.&nbsp;</span>
<Acheak @click="ChangeChildBag('2')" :on-value="type_ch" on-cheak="2">九宫</Acheak>
<span>&nbsp;.&nbsp;</span>
<Acheak @click="ChangeChildBag('3')" :on-value="type_ch" on-cheak="3">圣痕</Acheak>
<span>&nbsp;.&nbsp;</span>
<Acheak @click="ChangeChildBag('4')" :on-value="type_ch" on-cheak="4">礼包</Acheak>
<span>&nbsp;.&nbsp;</span>
<Acheak @click="ChangeChildBag('5')" :on-value="type_ch" on-cheak="5">材料</Acheak>
<span>&nbsp;.&nbsp;</span>
<Acheak @click="ChangeChildBag('6')" :on-value="type_ch" on-cheak="6">图纸</Acheak>
<span>&nbsp;.&nbsp;</span>
<Acheak @click="ChangeChildBag('7')" :on-value="type_ch" on-cheak="7">卡片</Acheak>
<span>&nbsp;.&nbsp;</span>
<Acheak @click="ChangeChildBag('8')" :on-value="type_ch" on-cheak="8">货物</Acheak>
<span>&nbsp;.&nbsp;</span>
<Acheak @click="ChangeChildBag('9')" :on-value="type_ch" on-cheak="9">其他</Acheak>
</div>
</div>

View File

@@ -0,0 +1,38 @@
export class FightService {
/**
* 添加怪物战斗
* POST /Fight/FightMonster
* @param type body
* @param monsterId body
* @param sign body
*/
static async FightMonster(type: number, monsterId: string, sign: string) {
return await ApiService.Request("post", "/Fight/FightMonster", { type, monsterId, sign });
}
/**
* 战斗接口
* POST /Fight/Fight
* @param fightId body
* @param data body
*/
static async Fight(fightId: string, data: string) {
return await ApiService.Request("post", "/Fight/Fight", { fightId, data });
}
/**
* 退出战斗
* GET /Fight/Exit
*/
static async Exit(fightId: string) {
return await ApiService.Request("get", "/Fight/Exit", { fightId });
}
/**
* 使用药品
* GET /Fight/UseFightDrug
*/
static async UseFightDrug(fightId: string, drugId: string) {
return await ApiService.Request("get", "/Fight/UseFightDrug", { fightId, drugId });
}
}

View File

@@ -0,0 +1,171 @@
interface IUnitFight {
atkHarm: number,
defHarm: number,
stateData: Array<string>,
remData: Array<any>,
}
export class FightTool {
public static FightHandle(atkUser: IUserAttr, defUser: IUserAttr): IFightData {
let result = 0;
let myHarm = 0;
let otHarm = 0;
let myStateData: Array<string> = [];
let myRemData: Array<any> = [];
let otStateData: Array<string> = [];
let otRemData: Array<any> = [];
var atkHandle = this.UnitFight(atkUser, defUser);
myHarm += atkHandle.atkHarm;
otHarm += atkHandle.defHarm;
otStateData.push(...atkHandle.stateData);
otRemData.push(...atkHandle.remData);
if (defUser.isSystem == 1) {
var defHandle = this.UnitFight(defUser, atkUser);
myHarm += defHandle.defHarm;
otHarm += defHandle.atkHarm;
myStateData.push(...defHandle.stateData);
myRemData.push(...defHandle.remData);
}
return {
result,
myHarm,
otHarm,
myStateData,
myRemData,
otStateData,
otRemData
};
}
private static UnitFight(atkUser: IUserAttr, defUser: IUserAttr): IUnitFight {
let atkHarm = 0;
let defHarm = 0;
let stateData: Array<string> = [];
let remData: Array<any> = [];
//闪避处理
if (defUser.dodge > 0) {
let dodgeRide = defUser.dodge - atkUser.deadly + defUser.deadlyLess;
if (dodgeRide > 0) {
if (this.randomTrigger(dodgeRide)) {
return {
atkHarm: 0,
defHarm: 0,
stateData,
remData
};
}
}
}
//士气处理
if (atkUser.upMorale > 0) {
atkUser.minAtk = atkUser.minAtk * (1.0 + (atkUser.morale / atkUser.upMorale) * 0.3);
}
if (defUser.upBlood > 0) {
defUser.defense = defUser.defense * (1.0 + (atkUser.morale / atkUser.upMorale) * 0.3);
}
if (atkUser.minAtk > defUser.defense && defUser.defense > 0) {
let harmRide = (atkUser.minAtk - defUser.defense) / defUser.defense;
harmRide = harmRide > 1.2 ? 1.2 : harmRide;
let fight_Harm = harmRide * atkUser.maxAtk;
defHarm += 0 - fight_Harm;
}
else {
defHarm = -1;
}
//暴击处理
if (atkUser.crit > 0) {
if (this.randomTrigger(atkUser.crit)) {
defHarm = defHarm * 1.5;
}
}
//处理反弹
if (defUser.rebound > 0) {
let reboundRide = defUser.rebound = atkUser.reboundLess;
if (reboundRide > 0) {
atkHarm = defHarm * reboundRide;
}
}
defHarm += 0 - atkUser.harm_Add;//额外伤害
//连击处理
if (atkUser.atk_Next > 0) {
if (this.randomTrigger(atkUser.atk_Next)) {
defHarm = defHarm * 1.3;
atkHarm = atkHarm * 1.3;
}
}
//免伤处理
if (defUser.noHarm > 0 && defHarm < -1) {
defHarm = defHarm * (1 - defUser.noHarm);
defHarm = defHarm > 0 ? 0 : defHarm;
}
//吸血处理
if (defHarm < 0 && atkUser.inBlood > 0) {
let inBloodRide = atkUser.inBlood - defUser.punish
if (inBloodRide > 0) {
atkHarm += (0 - defHarm) * inBloodRide;
}
}
//#region 状态类处理
let slow = atkUser.slow - defUser.slowLess;
if (this.randomTrigger(slow)) {
stateData.push("Slow");
}
let poison = atkUser.poison - defUser.poisonLess;
if (this.randomTrigger(poison)) {
stateData.push("Poison");
}
let curse = atkUser.curse - defUser.curseLess;
if (this.randomTrigger(curse)) {
stateData.push("Curse");
}
let weaken = atkUser.weaken - defUser.weakenLess;
if (this.randomTrigger(weaken)) {
stateData.push("Weaken");
}
let depressed = atkUser.depressed - defUser.depressedLess;
if (this.randomTrigger(depressed)) {
stateData.push("Depressed");
}
let breach = atkUser.breach - defUser.breachLess;
if (this.randomTrigger(breach)) {
stateData.push("Breach");
}
let palsyatk = atkUser.palsyAtk - defUser.palsyAtkLess;
if (this.randomTrigger(palsyatk)) {
stateData.push("PalsyAtk");
}
if (this.randomTrigger(atkUser.del_Fashion)) {
if (defUser.code == 'Person') {
remData.push({
"code": "equ",
"par": "Fashion",
"count": 1
});
}
}
//#endregion
//数值处理
atkHarm = Math.floor(atkHarm);
defHarm = Math.floor(defHarm);
return {
atkHarm,
defHarm,
stateData,
remData
};
}
private static randomTrigger(rate: number): boolean {
// Math.random() 返回 [0,1) 浮点
const rand = Math.random();
return rand < rate;
}
}