diff --git a/docs/游戏机制与平衡性调整更新草案.md b/docs/游戏机制与平衡性调整更新草案.md index 3078a65..b178d45 100644 --- a/docs/游戏机制与平衡性调整更新草案.md +++ b/docs/游戏机制与平衡性调整更新草案.md @@ -80,7 +80,8 @@ v1.6 - 新造的Robot的PlayerId的n总是尽量小 1. UseRobot - CD:2s,持续时间:0s - - 输入额外参数PlayerID,切换到要使用的角色 + - 输入额外参数PlayerID,切换到要使用的角色。 + - 切换到其他角色时,自己进入UsingSkill状态。 修改后: @@ -107,7 +108,7 @@ v1.6 - 被动技能Lucky!(新增):开局获得随机的一个道具(不会是钥匙) - 主动技能SparksNSplash(新增): - CD:45s, 持续时间:10s - - 技能使用瞬间,对于输入的额外参数PlayerID代表的角色,距离最近的本已停止运动的小炸弹开始追踪该角色(每50ms向该角色直线移动) + - 技能使用瞬间,对于输入的额外参数PlayerID代表的角色,距离最近的本已停止运动的小炸弹开始追踪该角色(每100ms向该角色直线移动)(该角色无血量则失败) - 主动技能 蹦蹦炸弹 JumpyBomb - 当蹦蹦炸弹因为碰撞而爆炸,向子弹方向上加上0°,45°,90°,135°,180°,225°,270°,315° 发出8个小炸弹 - Idol diff --git a/docs/版本更新说明.md b/docs/版本更新说明.md index 206dc81..1f21808 100644 --- a/docs/版本更新说明.md +++ b/docs/版本更新说明.md @@ -36,4 +36,10 @@ # 5月15日更新 - feat:Robot可用 -- hotfix: 修复了移动相关的bug \ No newline at end of file +- hotfix: 修复了移动相关的bug + +# 最新更新 +- feat:TechOtaku可用 +- feat:Klee、Idol已调整 +- fix:修复了InSpire会给Tricker加速的问题 +- fix:修复了开锁门的bug \ No newline at end of file diff --git a/logic/Client/MainWindow.xaml.cs b/logic/Client/MainWindow.xaml.cs index 7c5701f..1ac24a7 100644 --- a/logic/Client/MainWindow.xaml.cs +++ b/logic/Client/MainWindow.xaml.cs @@ -816,63 +816,63 @@ namespace Client private void Refresh(object? sender, EventArgs e) //log未更新 { - lock (drawPicLock) // 加锁是必要的,画图操作和接收信息操作不能同时进行 + try { - // Bonus(); - if (WindowState == WindowState.Maximized) - MaxButton.Content = "❐"; - else - MaxButton.Content = "🗖"; - foreach (var obj in listOfHuman) + lock (drawPicLock) // 加锁是必要的,画图操作和接收信息操作不能同时进行 { - if (!isDataFixed[obj.PlayerId] && obj.PlayerId < GameData.numOfStudent && obj.StudentType != StudentType.Robot) + // Bonus(); + if (WindowState == WindowState.Maximized) + MaxButton.Content = "❐"; + else + MaxButton.Content = "🗖"; + foreach (var obj in listOfHuman) { - IStudentType occupation = (IStudentType)OccupationFactory.FindIOccupation(Transformation.ToStudentType(obj.StudentType)); - totalLife[obj.PlayerId] = occupation.MaxHp; - totalDeath[obj.PlayerId] = occupation.MaxGamingAddiction; - int i = 0; - foreach (var skill in occupation.ListOfIActiveSkill) + if (obj.PlayerId < GameData.numOfStudent && !isDataFixed[obj.PlayerId]) { - var iActiveSkill = SkillFactory.FindActiveSkill(skill); - coolTime[i, obj.PlayerId] = iActiveSkill.SkillCD; - ++i; + IStudentType occupation = (IStudentType)OccupationFactory.FindIOccupation(Transformation.ToStudentType(obj.StudentType)); + totalLife[obj.PlayerId] = occupation.MaxHp; + totalDeath[obj.PlayerId] = occupation.MaxGamingAddiction; + int i = 0; + foreach (var skill in occupation.ListOfIActiveSkill) + { + var iActiveSkill = SkillFactory.FindActiveSkill(skill); + coolTime[i, obj.PlayerId] = iActiveSkill.SkillCD; + ++i; + } + isDataFixed[obj.PlayerId] = true; } - isDataFixed[obj.PlayerId] = true; } - } - foreach (var obj in listOfButcher) - { - if (!isDataFixed[obj.PlayerId]) + foreach (var obj in listOfButcher) { - IGhostType occupation1 = (IGhostType)OccupationFactory.FindIOccupation(Transformation.ToTrickerType(obj.TrickerType)); - int j = 0; - foreach (var skill in occupation1.ListOfIActiveSkill) + if (!isDataFixed[obj.PlayerId]) { - var iActiveSkill = SkillFactory.FindActiveSkill(skill); - coolTime[j, GameData.numOfStudent] = iActiveSkill.SkillCD; - ++j; + IGhostType occupation1 = (IGhostType)OccupationFactory.FindIOccupation(Transformation.ToTrickerType(obj.TrickerType)); + int j = 0; + foreach (var skill in occupation1.ListOfIActiveSkill) + { + var iActiveSkill = SkillFactory.FindActiveSkill(skill); + coolTime[j, GameData.numOfStudent] = iActiveSkill.SkillCD; + ++j; + } + isDataFixed[obj.PlayerId] = true; } - isDataFixed[obj.PlayerId] = true; } - } - for (int i = 0; i < GameData.numOfStudent; i++) - { - StatusBarsOfSurvivor[i].NewData(totalLife, totalDeath, coolTime); - } + for (int i = 0; i < GameData.numOfStudent; i++) + { + StatusBarsOfSurvivor[i].NewData(totalLife, totalDeath, coolTime); + } - StatusBarsOfHunter.NewData(totalLife, totalDeath, coolTime); + StatusBarsOfHunter.NewData(totalLife, totalDeath, coolTime); - for (int i = 0; i < GameData.numOfStudent; i++) - { - StatusBarsOfSurvivor[i].SetFontSize(12 * unitFontsize); - } + for (int i = 0; i < GameData.numOfStudent; i++) + { + StatusBarsOfSurvivor[i].SetFontSize(12 * unitFontsize); + } - StatusBarsOfHunter.SetFontSize(12 * unitFontsize); - StatusBarsOfCircumstance.SetFontSize(12 * unitFontsize); - if (!isClientStocked) - { - try + StatusBarsOfHunter.SetFontSize(12 * unitFontsize); + StatusBarsOfCircumstance.SetFontSize(12 * unitFontsize); + if (!isClientStocked) { UpperLayerOfMap.Children.Clear(); foreach (var data in listOfAll) @@ -885,7 +885,7 @@ namespace Client } foreach (var data in listOfHuman) { - if (data.StudentType != StudentType.Robot) + if (data.PlayerId < GameData.numOfStudent) StatusBarsOfSurvivor[data.PlayerId].SetValue(data, data.PlayerId); if (CanSee(data)) { @@ -1136,15 +1136,15 @@ namespace Client } } } - catch (Exception exc) - { - ErrorDisplayer error = new("Error: " + exc.ToString()); - error.Show(); - isClientStocked = true; - PorC.Content = "▶"; - } + counter++; } - counter++; + } + catch (Exception exc) + { + ErrorDisplayer error = new("Error: " + exc.ToString()); + error.Show(); + isClientStocked = true; + PorC.Content = "▶"; } } @@ -1309,6 +1309,7 @@ namespace Client { PlayerId = playerID, SkillId = 0, + SkillParam = 0, }; client.UseSkill(msgB); break; diff --git a/logic/GameClass/GameObj/Character/Character.BuffManager.cs b/logic/GameClass/GameObj/Character/Character.BuffManager.cs index 9c742d9..1677eaa 100644 --- a/logic/GameClass/GameObj/Character/Character.BuffManager.cs +++ b/logic/GameClass/GameObj/Character/Character.BuffManager.cs @@ -197,6 +197,19 @@ namespace GameClass.GameObj return false; } + public bool TryDeleteInvisible() + { + if (HasInvisible) + { + lock (buffListLock[(int)BuffType.Invisible]) + { + buffList[(int)BuffType.Invisible].RemoveFirst(); + } + return true; + } + return false; + } + public void AddClairaudience(int shieldTime) => AddBuff(new BuffValue(), shieldTime, BuffType.Clairaudience, () => { }); public bool HasClairaudience diff --git a/logic/GameClass/GameObj/Character/Character.cs b/logic/GameClass/GameObj/Character/Character.cs index 10e9523..e5f9071 100644 --- a/logic/GameClass/GameObj/Character/Character.cs +++ b/logic/GameClass/GameObj/Character/Character.cs @@ -361,7 +361,7 @@ namespace GameClass.GameObj { lock (actionLock) { - if (playerState == PlayerStateType.Null && IsMoving) return PlayerStateType.Moving; + if (playerState == PlayerStateType.Moving && IsMoving == 1) return PlayerStateType.Moving; return playerState; } } @@ -423,9 +423,7 @@ namespace GameClass.GameObj { //只能被SetPlayerState引用 whatInteractingWith = gameObj; - if (value != PlayerStateType.Moving) - IsMoving = false; - playerState = (value == PlayerStateType.Moving) ? PlayerStateType.Null : value; + playerState = value; //Debugger.Output(this,playerState.ToString()+" "+IsMoving.ToString()); return ++stateNum; } @@ -434,20 +432,19 @@ namespace GameClass.GameObj { //只能被SetPlayerState引用 whatInteractingWith = gameObj; - if (value != PlayerStateType.Moving) - IsMoving = false; - playerState = (value == PlayerStateType.Moving) ? PlayerStateType.Null : value; + playerState = value; //Debugger.Output(this,playerState.ToString()+" "+IsMoving.ToString()); return stateNum; } - public long SetPlayerState(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null) + public long SetPlayerState(PlayerStateType value = PlayerStateType.Null, IGameObj? obj = null) { + GameObj? gameObj = (GameObj?)obj; lock (actionLock) { PlayerStateType nowPlayerState = PlayerState; - if (nowPlayerState == value) return -1; + if (nowPlayerState == value && value != PlayerStateType.UsingSkill) return -1; switch (nowPlayerState) { case PlayerStateType.Escaped: @@ -468,20 +465,21 @@ namespace GameClass.GameObj else return -1; case PlayerStateType.TryingToAttack: - if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows - && value != PlayerStateType.LockingTheDoor && value != PlayerStateType.OpeningTheDoor) + if (value == PlayerStateType.Addicted || value == PlayerStateType.Swinging + || value == PlayerStateType.Deceased || value == PlayerStateType.Stunned + || value == PlayerStateType.Charmed || value == PlayerStateType.Null) return ChangePlayerState(value, gameObj); else return -1; case PlayerStateType.Stunned: case PlayerStateType.Charmed: - if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows - && value != PlayerStateType.LockingTheDoor && value != PlayerStateType.OpeningTheDoor - && value != PlayerStateType.Swinging) + if (value == PlayerStateType.Addicted || value == PlayerStateType.Deceased + || value == PlayerStateType.Null) return ChangePlayerState(value, gameObj); else return -1; case PlayerStateType.Swinging: - if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows - && value != PlayerStateType.LockingTheDoor && value != PlayerStateType.OpeningTheDoor) + if (value == PlayerStateType.Addicted + || value == PlayerStateType.Deceased || value == PlayerStateType.Stunned + || value == PlayerStateType.Charmed || value == PlayerStateType.Null) { try { @@ -494,7 +492,9 @@ namespace GameClass.GameObj } else return -1; case PlayerStateType.ClimbingThroughWindows: - if (value != PlayerStateType.Moving && value != PlayerStateType.LockingTheDoor && value != PlayerStateType.OpeningTheDoor) + if (value == PlayerStateType.Addicted + || value == PlayerStateType.Deceased || value == PlayerStateType.Stunned + || value == PlayerStateType.Charmed || value == PlayerStateType.Null) { Window window = (Window)WhatInteractingWith!; try @@ -537,6 +537,28 @@ namespace GameClass.GameObj { ThreadNum.Release(); } + case PlayerStateType.UsingSkill: + if (CharacterType == CharacterType.TechOtaku) + { + if (typeof(CraftingBench).IsInstanceOfType(whatInteractingWith)) + { + try + { + ((CraftingBench)whatInteractingWith!).StopSkill(); + return ChangePlayerState(value, gameObj); + } + finally + { + ThreadNum.Release(); + } + } + else + { + if (value != PlayerStateType.UsingSkill) + ((UseRobot)FindActiveSkill(ActiveSkillType.UseRobot)).NowPlayerID = (int)playerID; + } + } + return ChangePlayerState(value, gameObj); default: return ChangePlayerState(value, gameObj); } @@ -548,7 +570,6 @@ namespace GameClass.GameObj lock (actionLock) { whatInteractingWith = null; - IsMoving = false; playerState = PlayerStateType.Null; return ++stateNum; } @@ -777,6 +798,7 @@ namespace GameClass.GameObj return false; } } + public void TryActivatingLIFE() { if (buffManager.TryActivatingLIFE()) @@ -801,6 +823,11 @@ namespace GameClass.GameObj return buffManager.TryUseSpear(); } + public bool TryDeleteInvisible() + { + return buffManager.TryDeleteInvisible(); + } + public bool TryUseShield() { if (buffManager.TryUseShield()) diff --git a/logic/GameClass/GameObj/GameObj.cs b/logic/GameClass/GameObj/GameObj.cs index 9181015..eb8dcaf 100644 --- a/logic/GameClass/GameObj/GameObj.cs +++ b/logic/GameClass/GameObj/GameObj.cs @@ -36,6 +36,35 @@ namespace GameClass.GameObj public abstract ShapeType Shape { get; } + protected bool isRemoved = false; + public virtual bool IsRemoved + { + get + { + gameObjReaderWriterLock.EnterReadLock(); + try + { + return isRemoved; + } + finally + { + gameObjReaderWriterLock.ExitReadLock(); + } + } + } + public virtual void TryToRemove() + { + gameObjReaderWriterLock.EnterWriteLock(); + try + { + isRemoved = true; + } + finally + { + gameObjReaderWriterLock.ExitWriteLock(); + } + } + public int Radius { get; } public virtual bool IgnoreCollideExecutor(IGameObj targetObj) => false; diff --git a/logic/GameClass/GameObj/Map/Door.cs b/logic/GameClass/GameObj/Map/Door.cs index 9684a08..a019c66 100644 --- a/logic/GameClass/GameObj/Map/Door.cs +++ b/logic/GameClass/GameObj/Map/Door.cs @@ -97,7 +97,7 @@ namespace GameClass.GameObj { if (whoLockOrOpen != null) { - if (Environment.TickCount64 - openStartTime >= GameData.degreeOfLockingOrOpeningTheDoor) + if ((Environment.TickCount64 - openStartTime) >= GameData.degreeOfLockingOrOpeningTheDoor / whoLockOrOpen.SpeedOfOpeningOrLocking) isOpen = true; whoLockOrOpen = null; } @@ -128,7 +128,7 @@ namespace GameClass.GameObj lock (gameObjLock) { if (lockDegree >= GameData.degreeOfLockingOrOpeningTheDoor) - isOpen = true; + isOpen = false; whoLockOrOpen = null; } } diff --git a/logic/GameClass/GameObj/Map/Map.cs b/logic/GameClass/GameObj/Map/Map.cs index 8626712..311443a 100644 --- a/logic/GameClass/GameObj/Map/Map.cs +++ b/logic/GameClass/GameObj/Map/Map.cs @@ -231,7 +231,10 @@ namespace GameClass.GameObj } } if (ToDel != null) + { GameObjDict[gameObj.Type].Remove(ToDel); + ToDel.TryToRemove(); + } } finally { @@ -242,16 +245,19 @@ namespace GameClass.GameObj public bool RemoveJustFromMap(GameObj gameObj) { GameObjLockDict[gameObj.Type].EnterWriteLock(); - bool flag; try { - flag = GameObjDict[gameObj.Type].Remove(gameObj); + if (GameObjDict[gameObj.Type].Remove(gameObj)) + { + gameObj.TryToRemove(); + return true; + } + return false; } finally { GameObjLockDict[gameObj.Type].ExitWriteLock(); } - return flag; } public void Add(GameObj gameObj) { diff --git a/logic/GameClass/GameObj/Moveable.cs b/logic/GameClass/GameObj/Moveable.cs index 1600361..7f9c74f 100644 --- a/logic/GameClass/GameObj/Moveable.cs +++ b/logic/GameClass/GameObj/Moveable.cs @@ -47,21 +47,11 @@ namespace GameClass.GameObj } } - private bool isMoving; - public bool IsMoving + private int isMoving = 0; + public int IsMoving { - get - { - lock (actionLock) - return isMoving; - } - set - { - lock (actionLock) - { - isMoving = value; - } - } + get => Interlocked.CompareExchange(ref isMoving, 0, 1); + set => Interlocked.Exchange(ref isMoving, value); } // 移动,改变坐标 @@ -126,8 +116,7 @@ namespace GameClass.GameObj } } - protected bool isRemoved; - public bool IsRemoved + public override bool IsRemoved { get { @@ -152,7 +141,7 @@ namespace GameClass.GameObj moveReaderWriterLock.EnterReadLock(); try { - return !isMoving && canMove && !isRemoved; + return isMoving == 0 && canMove && !isRemoved; } finally { diff --git a/logic/GameClass/GameObj/ObjOfCharacter.cs b/logic/GameClass/GameObj/ObjOfCharacter.cs index 7bdcba1..5f24566 100644 --- a/logic/GameClass/GameObj/ObjOfCharacter.cs +++ b/logic/GameClass/GameObj/ObjOfCharacter.cs @@ -1,5 +1,4 @@ -using Google.Protobuf.WellKnownTypes; -using Preparation.Interface; +using Preparation.Interface; using Preparation.Utility; using System.Threading; diff --git a/logic/GameClass/GameObj/Prop/Item.cs b/logic/GameClass/GameObj/Prop/Item.cs index c8838a5..b4d3ea0 100644 --- a/logic/GameClass/GameObj/Prop/Item.cs +++ b/logic/GameClass/GameObj/Prop/Item.cs @@ -1,5 +1,6 @@ using Preparation.Interface; using Preparation.Utility; +using System.Threading; namespace GameClass.GameObj { @@ -32,9 +33,32 @@ namespace GameClass.GameObj public sealed class CraftingBench : Item { - public CraftingBench(XY initPos) : + public CraftingBench(XY initPos, Character character, int num) : base(initPos) { + Parent = character; + this.num = num; + } + private readonly int num; + private long parentStateNum; + public long ParentStateNum + { + get => Interlocked.Read(ref parentStateNum); + set => Interlocked.Exchange(ref parentStateNum, value); + } + public void StopSkill() + { + ((SummonGolem)Parent!.FindActiveSkill(ActiveSkillType.SummonGolem)).DeleteGolem((int)num); + } + public void TryStopSkill() + { + lock (Parent!.ActionLock) + { + if (Parent!.StateNum == parentStateNum) + { + Parent!.SetPlayerState(); + } + } } public override PropType GetPropType() => PropType.CraftingBench; } diff --git a/logic/GameEngine/MoveEngine.cs b/logic/GameEngine/MoveEngine.cs index c3f0d45..c94d3cd 100644 --- a/logic/GameEngine/MoveEngine.cs +++ b/logic/GameEngine/MoveEngine.cs @@ -102,7 +102,7 @@ namespace GameEngine lock (obj.ActionLock) { if (!obj.IsAvailableForMove) { EndMove(obj); return; } - obj.IsMoving = true; + obj.IsMoving = 1; } new Thread @@ -139,7 +139,7 @@ namespace GameEngine if (isEnded) { - obj.IsMoving = false; + obj.IsMoving = 0; EndMove(obj); return; } @@ -184,7 +184,7 @@ namespace GameEngine } if (isEnded) { - obj.IsMoving = false; + obj.IsMoving = 0; EndMove(obj); return; } @@ -224,7 +224,7 @@ namespace GameEngine } } while (flag); } - obj.IsMoving = false; // 结束移动 + obj.IsMoving = 0; // 结束移动 EndMove(obj); } } diff --git a/logic/Gaming/ActionManager.cs b/logic/Gaming/ActionManager.cs index 569472f..2960c5c 100644 --- a/logic/Gaming/ActionManager.cs +++ b/logic/Gaming/ActionManager.cs @@ -1,4 +1,5 @@ using System; +using System.Numerics; using System.Threading; using GameClass.GameObj; using GameEngine; @@ -13,26 +14,6 @@ namespace Gaming private readonly ActionManager actionManager; private class ActionManager { - - // 人物移动 - private void SkillWhenColliding(Character player, IGameObj collisionObj) - { - if (collisionObj.Type == GameObjType.Bullet) - { - if (((Bullet)collisionObj).Parent != player && ((Bullet)collisionObj).TypeOfBullet == BulletType.JumpyDumpty) - { - if (characterManager.BeStunned((Character)player, GameData.timeOfStunnedWhenJumpyDumpty) > 0) - player.AddScore(GameData.TrickerScoreStudentBeStunned(GameData.timeOfStunnedWhenJumpyDumpty)); - gameMap.Remove((GameObj)collisionObj); - } - } - if (player.FindActiveSkill(ActiveSkillType.CanBeginToCharge).IsBeingUsed == 1 && collisionObj.Type == GameObjType.Character && ((Character)collisionObj).IsGhost()) - { - if (characterManager.BeStunned((Character)collisionObj, GameData.timeOfGhostStunnedWhenCharge) > 0) - player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.timeOfGhostStunnedWhenCharge)); - characterManager.BeStunned(player, GameData.timeOfStudentStunnedWhenCharge); - } - } public bool MovePlayer(Character playerToMove, int moveTimeInMilliseconds, double moveDirection) { if (moveTimeInMilliseconds < 5) return false; @@ -80,7 +61,7 @@ namespace Gaming return true; } - public bool Stop(Character player) + public static bool Stop(Character player) { lock (player.ActionLock) { @@ -95,7 +76,7 @@ namespace Gaming public bool Fix(Student player)// 自动检查有无发电机可修 { - if (player.CharacterType == CharacterType.Teacher || (!player.Commandable()) || player.PlayerState == PlayerStateType.Fixing) + if ((!player.Commandable()) || player.PlayerState == PlayerStateType.Fixing) return false; Generator? generatorForFix = (Generator?)gameMap.OneForInteract(player.Position, GameObjType.Generator); @@ -449,8 +430,11 @@ namespace Gaming ) .Start(); doorToLock.StopLock(); - if (stateNum == player.StateNum) player.SetPlayerState(); player.ReleaseTool(propType); + lock (player.ActionLock) + { + if (stateNum == player.StateNum) player.SetPlayerStateNaturally(); + } player.ThreadNum.Release(); } } @@ -500,9 +484,12 @@ namespace Gaming player.ReleaseTool(propType); lock (player.ActionLock) { - if (stateNum == player.StateNum) player.SetPlayerState(); + if (stateNum == player.StateNum) + { + player.SetPlayerStateNaturally(); + player.ThreadNum.Release(); + } } - player.ThreadNum.Release(); } else { @@ -512,7 +499,7 @@ namespace Gaming { if (stateNum == player.StateNum) { - player.SetPlayerState(); + player.SetPlayerStateNaturally(); doorToLock.StopOpen(); player.ReleaseTool(propType); player.ThreadNum.Release(); @@ -561,7 +548,37 @@ namespace Gaming gameMap: gameMap, OnCollision: (obj, collisionObj, moveVec) => { - SkillWhenColliding((Character)obj, collisionObj); + Character player = (Character)obj; + switch (collisionObj.Type) + { + case GameObjType.Bullet: + + if (((Bullet)collisionObj).Parent != player && ((Bullet)collisionObj).TypeOfBullet == BulletType.JumpyDumpty) + { + if (characterManager.BeStunned((Character)player, GameData.timeOfStunnedWhenJumpyDumpty) > 0) + player.AddScore(GameData.TrickerScoreStudentBeStunned(GameData.timeOfStunnedWhenJumpyDumpty)); + gameMap.Remove((GameObj)collisionObj); + } + break; + case GameObjType.Character: + if (player.FindActiveSkill(ActiveSkillType.CanBeginToCharge).IsBeingUsed == 1 && ((Character)collisionObj).IsGhost()) + { + if (characterManager.BeStunned((Character)collisionObj, GameData.timeOfGhostStunnedWhenCharge) > 0) + player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.timeOfGhostStunnedWhenCharge)); + characterManager.BeStunned(player, GameData.timeOfStudentStunnedWhenCharge); + } + break; + case GameObjType.Item: + if (((Item)collisionObj).GetPropType() == PropType.CraftingBench) + { + ((CraftingBench)collisionObj).TryStopSkill(); + gameMap.Remove((Item)collisionObj); + } + break; + default: + break; + } + //Preparation.Utility.Debugger.Output(obj, " end move with " + collisionObj.ToString()); //if (collisionObj is Mine) //{ diff --git a/logic/Gaming/AttackManager.cs b/logic/Gaming/AttackManager.cs index 36add52..a8ade02 100644 --- a/logic/Gaming/AttackManager.cs +++ b/logic/Gaming/AttackManager.cs @@ -15,7 +15,7 @@ namespace Gaming private class AttackManager { readonly Map gameMap; - readonly MoveEngine moveEngine; + public readonly MoveEngine moveEngine; readonly CharacterManager characterManager; public AttackManager(Map gameMap, CharacterManager characterManager) @@ -72,7 +72,14 @@ namespace Gaming break; case GameObjType.Door: if (bullet.CanBeBombed(GameObjType.Door)) - ; + ((Door)objBeingShot).ForceToOpen(); + break; + case GameObjType.Item: + if (((Item)objBeingShot).GetPropType() == PropType.CraftingBench) + { + ((CraftingBench)objBeingShot).TryStopSkill(); + gameMap.Remove(objBeingShot); + } break; default: break; @@ -102,6 +109,17 @@ namespace Gaming else return false; } + private void ProduceBombBomb(Bullet bullet, double angle) + { + angle += bullet.FacingDirection.Angle(); + XY pos = bullet.Position + new XY + ( + (int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Cos(angle))) * Math.Sign(Math.Cos(angle)), + (int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Sin(angle))) * Math.Sign(Math.Sin(angle)) + ); + ProduceBulletNaturally(BulletType.JumpyDumpty, (Character)bullet.Parent!, angle, pos); + } + private void BulletBomb(Bullet bullet, GameObj? objBeingShot) { #if DEBUG @@ -137,21 +155,14 @@ namespace Gaming if (bullet.TypeOfBullet == BulletType.BombBomb && objBeingShot != null) { - double angle = bullet.FacingDirection.Angle() + Math.PI / 2.0; - XY pos = bullet.Position + new XY // 子弹紧贴人物生成。 - ( - (int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Cos(angle))) * Math.Sign(Math.Cos(angle)), - (int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Sin(angle))) * Math.Sign(Math.Sin(angle)) - ); - ProduceBulletNaturally(BulletType.JumpyDumpty, (Character)bullet.Parent!, angle, pos); - - angle = bullet.FacingDirection.Angle() + Math.PI * 3.0 / 2.0; - pos = bullet.Position + new XY // 子弹紧贴人物生成。 - ( - (int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Cos(angle))) * Math.Sign(Math.Cos(angle)), - (int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Sin(angle))) * Math.Sign(Math.Sin(angle)) - ); - ProduceBulletNaturally(BulletType.JumpyDumpty, (Character)bullet.Parent!, angle, pos); + ProduceBombBomb(bullet, 0); + ProduceBombBomb(bullet, Math.PI / 4); + ProduceBombBomb(bullet, Math.PI / 2); + ProduceBombBomb(bullet, Math.PI * 3 / 4); + ProduceBombBomb(bullet, Math.PI); + ProduceBombBomb(bullet, Math.PI * 5 / 4); + ProduceBombBomb(bullet, Math.PI * 3 / 2); + ProduceBombBomb(bullet, Math.PI * 7 / 4); } var beAttackedList = new List(); diff --git a/logic/Gaming/CharacterManager.cs b/logic/Gaming/CharacterManager.cs index f7a3f19..614d6bf 100644 --- a/logic/Gaming/CharacterManager.cs +++ b/logic/Gaming/CharacterManager.cs @@ -383,7 +383,15 @@ namespace Gaming if (parent != null && parent.CharacterType == CharacterType.TechOtaku) { ((SummonGolem)(parent.FindActiveSkill(ActiveSkillType.SummonGolem))).DeleteGolem((int)(player.PlayerID - parent.PlayerID) / GameData.numOfPeople - 1); - //player.FindActiveSkill(ActiveSkillType.UseRobot).IsBeingUsed = false; + UseRobot useRobot = (UseRobot)parent.FindActiveSkill(ActiveSkillType.UseRobot); + if (useRobot.TryResetNowPlayerID((int)player.PlayerID)) + { + lock (parent.ActionLock) + { + if (parent.PlayerState == PlayerStateType.UsingSkill) + parent.SetPlayerState(); + } + } } return; } diff --git a/logic/Gaming/Game.cs b/logic/Gaming/Game.cs index 8a973c9..a76ac2a 100644 --- a/logic/Gaming/Game.cs +++ b/logic/Gaming/Game.cs @@ -160,7 +160,7 @@ namespace Gaming Character? player = gameMap.FindPlayerToAction(playerID); if (player != null) { - return actionManager.Stop(player); + return ActionManager.Stop(player); } return false; } diff --git a/logic/Gaming/PropManager.cs b/logic/Gaming/PropManager.cs index 4fe007c..67e29f2 100644 --- a/logic/Gaming/PropManager.cs +++ b/logic/Gaming/PropManager.cs @@ -5,8 +5,6 @@ using Preparation.Utility; using System; using Timothy.FrameRateTask; using GameEngine; -using System.Numerics; -using System.Reflection; namespace Gaming { diff --git a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs index 5d52443..7df2ef1 100644 --- a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs +++ b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs @@ -76,6 +76,7 @@ namespace Gaming } }, timeInterval: GameData.checkIntervalWhenShowTime, + maxTotalDuration: skill.DurationTime, finallyReturn: () => 0 ) @@ -104,17 +105,39 @@ namespace Gaming { }); } - public bool UseRobot(Character player) + public bool UseRobot(Character player, int robotID) { - /* - IGolem? golem = (IGolem?)(((SummonGolem)player.FindActiveSkill(ActiveSkillType.SummonGolem)).GolemSummoned); - if ((!player.Commandable()) || ((SummonGolem)player.FindActiveSkill(ActiveSkillType.SummonGolem)).GolemSummoned == null) return false; - Debugger.Output(player, "use robot!"); - IActiveSkill activeSkill = player.FindActiveSkill(ActiveSkillType.UseRobot); - activeSkill.IsBeingUsed = (activeSkill.IsBeingUsed) ? false : true; - if (activeSkill.IsBeingUsed) player.SetPlayerState(PlayerStateType.UsingSkill); - else player.SetPlayerState();*/ - return true; + if ((robotID - player.PlayerID) % GameData.numOfPeople != 0) return false; + if ((robotID - (int)player.PlayerID) / GameData.numOfPeople < 0 || (robotID - (int)player.PlayerID) / GameData.numOfPeople > GameData.maxSummonedGolemNum) return false; + UseRobot activeSkill = (UseRobot)player.FindActiveSkill(ActiveSkillType.UseRobot); + lock (activeSkill.ActiveSkillUseLock) + { + if (robotID == player.PlayerID) + { + lock (player.ActionLock) + { + if (player.PlayerState == PlayerStateType.UsingSkill && player.WhatInteractingWith == null) + player.SetPlayerStateNaturally(); + activeSkill.NowPlayerID = robotID; + } + } + else + { + SummonGolem summonGolemSkill = (SummonGolem)player.FindActiveSkill(ActiveSkillType.SummonGolem); + if (summonGolemSkill.GolemStateArray[(robotID - (int)player.PlayerID) / GameData.numOfPeople - 1] == 2) + { + activeSkill.NowPlayerID = robotID; + } + else return false; + long stateNum = player.SetPlayerState(PlayerStateType.UsingSkill); + if (stateNum == -1) + { + activeSkill.NowPlayerID = (int)player.PlayerID; + return false; + } + } + return ActiveSkillEffect(activeSkill, player, () => { }, () => { }); + } } public static bool JumpyBomb(Character player) @@ -129,6 +152,62 @@ namespace Gaming { player.BulletOfPlayer = player.OriBulletOfPlayer; }); } + public bool SparksNSplash(Character player, int AttackID) + { + Character? whoAttacked = gameMap.FindPlayer(AttackID); + if (whoAttacked == null || whoAttacked.NoHp()) return false; + ActiveSkill activeSkill = player.FindActiveSkill(ActiveSkillType.SparksNSplash); + + return ActiveSkillEffect(activeSkill, player, () => + { + new Thread + ( + () => + { + Bullet? homingMissile = null; + double dis; + new FrameRateTaskExecutor( + loopCondition: () => gameMap.Timer.IsGaming && !whoAttacked.NoHp(), + loopToDo: () => + { + dis = ((homingMissile == null || homingMissile.IsRemoved) ? double.MaxValue : XY.DistanceFloor3(homingMissile.Position, whoAttacked.Position)); + gameMap.GameObjLockDict[GameObjType.Bullet].EnterReadLock(); + try + { + foreach (Bullet bullet in gameMap.GameObjDict[GameObjType.Bullet]) + { + if (!bullet.CanMove && XY.DistanceFloor3(bullet.Position, whoAttacked.Position) < dis && bullet.TypeOfBullet == BulletType.JumpyDumpty) + { + homingMissile = bullet; + dis = XY.DistanceFloor3(bullet.Position, whoAttacked.Position); + } + } + } + finally + { + gameMap.GameObjLockDict[GameObjType.Bullet].ExitReadLock(); + } + if (homingMissile != null) + { + homingMissile.ReSetCanMove(true); + attackManager.moveEngine.MoveObj(homingMissile, GameData.checkIntervalWhenSparksNSplash - 1, (whoAttacked.Position - homingMissile.Position).Angle(), ++homingMissile.StateNum); + } + }, + timeInterval: GameData.checkIntervalWhenSparksNSplash, + maxTotalDuration: activeSkill.DurationTime, + finallyReturn: () => 0 + ) + + .Start(); + } + ) + { IsBackground = true }.Start(); + Debugger.Output(player, "uses sparks n splash!"); + }, + () => + { }); + } + public bool WriteAnswers(Character player) { if ((!player.Commandable())) return false; @@ -151,24 +230,61 @@ namespace Gaming public bool SummonGolem(Character player) { ActiveSkill activeSkill = player.FindActiveSkill(ActiveSkillType.SummonGolem); - long num = ((SummonGolem)activeSkill).AddGolem(); + int num = ((SummonGolem)activeSkill).BuildGolem(); if (num >= GameData.maxSummonedGolemNum) return false; - num = (num + 1) * GameData.numOfPeople + player.PlayerID; - /* if ((!player.Commandable())) return false; - XY res = player.Position + new XY(player.FacingDirection, player.Radius * 2); - if (actionManager.moveEngine.CheckCollision(player, res) != null) - return false; - Golem? golem = (Golem?)characterManager.AddPlayer(res, player.TeamID, player.PlayerID + GameData.numOfPeople, CharacterType.Robot, player); - if (golem == null) return false; - ((SummonGolem)activeSkill).GolemSummoned = golem; - */ - return ActiveSkillEffect(activeSkill, player, () => + XY res = player.Position + new XY(player.FacingDirection, player.Radius * 2); + lock (activeSkill.ActiveSkillUseLock) { - }, - () => - { }); + CraftingBench craftingBench = new(res, player, num); + + long stateNum = player.SetPlayerState(PlayerStateType.UsingSkill, craftingBench); + if (stateNum == -1) + { + ((SummonGolem)activeSkill).DeleteGolem(num); + return false; + } + + player.ThreadNum.WaitOne(); + if (stateNum != player.StateNum) + { + ((SummonGolem)activeSkill).DeleteGolem(num); + player.ThreadNum.Release(); + return false; + } + if (actionManager.moveEngine.CheckCollision(craftingBench, res) != null) + { + ((SummonGolem)activeSkill).DeleteGolem(num); + player.ThreadNum.Release(); + return false; + } + craftingBench.ParentStateNum = stateNum; + gameMap.Add(craftingBench); + /* + */ + return ActiveSkillEffect(activeSkill, player, () => + { + }, + () => + { + lock (player.ActionLock) + { + if (stateNum == player.StateNum) + { + gameMap.RemoveJustFromMap(craftingBench); + Golem? golem = (Golem?)characterManager.AddPlayer(res, player.TeamID, (num + 1) * GameData.numOfPeople + player.PlayerID, CharacterType.Robot, player); + if (golem == null) + { + ((SummonGolem)activeSkill).AddGolem(num); + } + player.SetPlayerStateNaturally(); + player.ThreadNum.Release(); + } + } + } + ); + } } public static bool UseKnife(Character player) @@ -312,7 +428,7 @@ namespace Gaming { foreach (Character character in gameMap.GameObjDict[GameObjType.Character]) { - if (gameMap.CanSee(player, character)) + if (gameMap.CanSee(player, character) && !character.IsGhost()) { player.AddScore(GameData.ScoreInspire); character.AddMoveSpeed(GameData.timeOfAddingSpeedWhenInspire, GameData.addedTimeOfSpeedWhenInspire); @@ -336,6 +452,7 @@ namespace Gaming if (activeSkill.TimeUntilActiveSkillAvailable == 0) { activeSkill.TimeUntilActiveSkillAvailable = activeSkill.SkillCD; + new Thread (() => { diff --git a/logic/Gaming/SkillManager/SkillManager.PassiveSkill.cs b/logic/Gaming/SkillManager/SkillManager.PassiveSkill.cs index e1b965f..0fe1925 100644 --- a/logic/Gaming/SkillManager/SkillManager.PassiveSkill.cs +++ b/logic/Gaming/SkillManager/SkillManager.PassiveSkill.cs @@ -53,6 +53,10 @@ namespace Gaming // 被动技能开局时就释放,持续到游戏结束 ) { IsBackground = true }.Start(); } + public void Lucky(Character player) + { + player.PropInventory[0] = PropFactory.GetConsumables((PropType)((4 * Environment.TickCount) % 5 + 4), new XY(0, 0)); + } } } } \ No newline at end of file diff --git a/logic/Gaming/SkillManager/SkillManager.cs b/logic/Gaming/SkillManager/SkillManager.cs index 754785d..fd2c21e 100644 --- a/logic/Gaming/SkillManager/SkillManager.cs +++ b/logic/Gaming/SkillManager/SkillManager.cs @@ -32,12 +32,14 @@ namespace Gaming return Punish(character); case ActiveSkillType.JumpyBomb: return JumpyBomb(character); + case ActiveSkillType.SparksNSplash: + return SparksNSplash(character, parameter); case ActiveSkillType.WriteAnswers: return WriteAnswers(character); case ActiveSkillType.SummonGolem: return SummonGolem(character); case ActiveSkillType.UseRobot: - return UseRobot(character); + return UseRobot(character, parameter); case ActiveSkillType.Rouse: return Rouse(character); case ActiveSkillType.ShowTime: @@ -47,7 +49,7 @@ namespace Gaming } return false; } - public void UsePassiveSkill(Character character, PassiveSkillType passiveSkillType) + /*public void UsePassiveSkill(Character character, PassiveSkillType passiveSkillType) { if (character.Occupation.ListOfIPassiveSkill.Contains(passiveSkillType)) switch (passiveSkillType) @@ -59,7 +61,7 @@ namespace Gaming return; } return; - } + }*/ public void UseAllPassiveSkill(Character character) { foreach (var passiveSkill in character.Occupation.ListOfIPassiveSkill) @@ -68,6 +70,9 @@ namespace Gaming case PassiveSkillType.Meditate: Meditate(character); break; + case PassiveSkillType.Lucky: + Lucky(character); + break; default: return; } diff --git a/logic/Preparation/Interface/ICharacter.cs b/logic/Preparation/Interface/ICharacter.cs index ae53359..7179b4b 100644 --- a/logic/Preparation/Interface/ICharacter.cs +++ b/logic/Preparation/Interface/ICharacter.cs @@ -3,7 +3,7 @@ using Preparation.Utility; namespace Preparation.Interface { - public interface ICharacter : IGameObj + public interface ICharacter : IMoveable { public long TeamID { get; } public int HP { get; set; } @@ -13,7 +13,9 @@ namespace Preparation.Interface public PlayerStateType PlayerState { get; } public BulletType BulletOfPlayer { get; set; } public CharacterType CharacterType { get; } + public ActiveSkill FindActiveSkill(ActiveSkillType activeSkillType); public int UpdateBulletNum(int time); + public long SetPlayerState(PlayerStateType value = PlayerStateType.Null, IGameObj? obj = null); public bool IsGhost(); } diff --git a/logic/Preparation/Interface/IMoveable.cs b/logic/Preparation/Interface/IMoveable.cs index ad87c31..e33c1fb 100644 --- a/logic/Preparation/Interface/IMoveable.cs +++ b/logic/Preparation/Interface/IMoveable.cs @@ -8,7 +8,7 @@ namespace Preparation.Interface { object ActionLock { get; } public int MoveSpeed { get; } - public bool IsMoving { get; set; } + public int IsMoving { get; set; } public bool IsRemoved { get; } public bool IsAvailableForMove { get; } public long StateNum { get; } diff --git a/logic/Preparation/Interface/IOccupation.cs b/logic/Preparation/Interface/IOccupation.cs index de436ff..7d21a67 100644 --- a/logic/Preparation/Interface/IOccupation.cs +++ b/logic/Preparation/Interface/IOccupation.cs @@ -70,8 +70,8 @@ namespace Preparation.Interface public BulletType InitBullet => BulletType.CommonAttackOfGhost; - public List ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.JumpyBomb }); - public List ListOfIPassiveSkill => new(new PassiveSkillType[] { }); + public List ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.JumpyBomb, ActiveSkillType.SparksNSplash }); + public List ListOfIPassiveSkill => new(new PassiveSkillType[] { PassiveSkillType.Lucky }); public double concealment = GameData.basicConcealment; public double Concealment => concealment; @@ -169,7 +169,7 @@ namespace Preparation.Interface public List ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.Punish }); public List ListOfIPassiveSkill => new(new PassiveSkillType[] { }); - public const int fixSpeed = 0; + public const int fixSpeed = 50; public int FixSpeed => fixSpeed; public const int treatSpeed = (int)(GameData.basicTreatSpeed * 0.8); @@ -178,16 +178,16 @@ namespace Preparation.Interface public const double concealment = GameData.basicConcealment * 0.5; public double Concealment => concealment; - public const int alertnessRadius = GameData.basicStudentAlertnessRadius / 2; + public const int alertnessRadius = GameData.basicStudentAlertnessRadius * 2 / 3; public int AlertnessRadius => alertnessRadius; - public int viewRange = GameData.basicStudentViewRange * 9 / 10; + public int viewRange = GameData.basicStudentViewRange * 8 / 10; public int ViewRange => viewRange; public int speedOfOpeningOrLocking = GameData.basicSpeedOfOpeningOrLocking; public int SpeedOfOpeningOrLocking => speedOfOpeningOrLocking; - public int speedOfClimbingThroughWindows = GameData.basicStudentSpeedOfClimbingThroughWindows / 2; + public int speedOfClimbingThroughWindows = GameData.basicStudentSpeedOfClimbingThroughWindows * 1000 / 1222; public int SpeedOfClimbingThroughWindows => speedOfClimbingThroughWindows; public int speedOfOpenChest = GameData.basicSpeedOfOpenChest; diff --git a/logic/Preparation/Interface/ISkill.cs b/logic/Preparation/Interface/ISkill.cs index 0d9e29d..b06f1a0 100644 --- a/logic/Preparation/Interface/ISkill.cs +++ b/logic/Preparation/Interface/ISkill.cs @@ -32,7 +32,10 @@ namespace Preparation.Interface private int timeUntilActiveSkillAvailable = 0; public int TimeUntilActiveSkillAvailable { - get => Interlocked.CompareExchange(ref timeUntilActiveSkillAvailable, 0, 1); + get + { + return Interlocked.CompareExchange(ref timeUntilActiveSkillAvailable, 0, 1); + } set { if (value < 0) value = 0; @@ -103,6 +106,12 @@ namespace Preparation.Interface public override int DurationTime => GameData.commonSkillTime * 3 / 10; } + public class SparksNSplash : ActiveSkill + { + public override int SkillCD => GameData.commonSkillCD * 45 / 30; + public override int DurationTime => GameData.commonSkillTime; + } + public class UseKnife : ActiveSkill { public override int SkillCD => GameData.commonSkillCD; @@ -117,8 +126,32 @@ namespace Preparation.Interface private int nowPlayerID; public int NowPlayerID { - get => Interlocked.CompareExchange(ref nowPlayerID, 0, 1); - set => Interlocked.Exchange(ref nowPlayerID, value); + get + { + lock (SkillLock) + { + return nowPlayerID; + } + } + set + { + lock (SkillLock) + { + nowPlayerID = value; + } + } + } + public bool TryResetNowPlayerID(int tryPlayerID) + { + lock (SkillLock) + { + if (nowPlayerID == tryPlayerID) + { + nowPlayerID %= GameData.numOfPeople; + return true; + } + else return false; + } } } @@ -138,14 +171,15 @@ namespace Preparation.Interface public class SummonGolem : ActiveSkill { public override int SkillCD => GameData.commonSkillCD * 4 / 3; - public override int DurationTime => 6; + public override int DurationTime => 6000; - private bool[] golemIDArray = new bool[GameData.maxSummonedGolemNum] { false, false, false }; - public bool[] GolemIDArray + private int[] golemStateArray = new int[GameData.maxSummonedGolemNum] { 0, 0, 0 }; + //0未建造,1建造中,2已建造 + public int[] GolemStateArray { get { - lock (SkillLock) { return golemIDArray; } + lock (SkillLock) { return golemStateArray; } } } private int nowPtr = 0; @@ -156,14 +190,14 @@ namespace Preparation.Interface lock (SkillLock) { return nowPtr; } } } - public int AddGolem() + public int BuildGolem() { lock (SkillLock) { if (nowPtr == GameData.maxSummonedGolemNum) return GameData.maxSummonedGolemNum; int num = nowPtr; - golemIDArray[nowPtr] = true; - while ((++nowPtr) < GameData.maxSummonedGolemNum && golemIDArray[nowPtr]) ; + golemStateArray[nowPtr] = 1; + while ((++nowPtr) < GameData.maxSummonedGolemNum && golemStateArray[nowPtr] != 0) ; return num; } } @@ -171,13 +205,20 @@ namespace Preparation.Interface { lock (SkillLock) { - golemIDArray[num] = false; + golemStateArray[num] = 0; if (num < nowPtr) { nowPtr = num; } } } + public void AddGolem(int num) + { + lock (SkillLock) + { + golemStateArray[num] = 2; + } + } } public class NullSkill : ActiveSkill @@ -206,6 +247,8 @@ namespace Preparation.Interface return new Punish(); case ActiveSkillType.JumpyBomb: return new JumpyBomb(); + case ActiveSkillType.SparksNSplash: + return new SparksNSplash(); case ActiveSkillType.WriteAnswers: return new WriteAnswers(); case ActiveSkillType.SummonGolem: @@ -243,6 +286,8 @@ namespace Preparation.Interface return ActiveSkillType.Punish; case JumpyBomb: return ActiveSkillType.JumpyBomb; + case SparksNSplash: + return ActiveSkillType.SparksNSplash; case WriteAnswers: return ActiveSkillType.WriteAnswers; case SummonGolem: diff --git a/logic/Preparation/Utility/Debugger.cs b/logic/Preparation/Utility/Debugger.cs index 282d9b3..8627e31 100644 --- a/logic/Preparation/Utility/Debugger.cs +++ b/logic/Preparation/Utility/Debugger.cs @@ -8,6 +8,12 @@ namespace Preparation.Utility { #if DEBUG Console.WriteLine(current.GetType() + " " + current.ToString() + " " + str); +#endif + } + static public void Output(string str) + { +#if DEBUG + Console.WriteLine(str); #endif } } diff --git a/logic/Preparation/Utility/EnumType.cs b/logic/Preparation/Utility/EnumType.cs index 0608e60..2d7329b 100644 --- a/logic/Preparation/Utility/EnumType.cs +++ b/logic/Preparation/Utility/EnumType.cs @@ -105,11 +105,12 @@ namespace Preparation.Utility Encourage = 12, Inspire = 13, ShowTime = 14, + SparksNSplash = 15, } public enum PassiveSkillType { Null = 0, - BecomeInvisible = 1, + Lucky = 1, BecomeVampire = 2, NuclearWeapon = 3, SuperFast = 4, diff --git a/logic/Preparation/Utility/GameData.cs b/logic/Preparation/Utility/GameData.cs index 41bf740..2d3ccbe 100644 --- a/logic/Preparation/Utility/GameData.cs +++ b/logic/Preparation/Utility/GameData.cs @@ -220,13 +220,14 @@ namespace Preparation.Utility public const int timeOfStudentStunnedWhenHowl = 5500; public const int timeOfStunnedWhenJumpyDumpty = 3070; + public const int checkIntervalWhenSparksNSplash = 100; public const double addedTimeOfSpeedWhenInspire = 1.6; public const int timeOfAddingSpeedWhenInspire = 6000; public const int addHpWhenEncourage = basicHp / 4; - public const int checkIntervalWhenShowTime = 200; + public const int checkIntervalWhenShowTime = 500; public const int addAddictionPer100msWhenShowTime = 300; public const int maxSummonedGolemNum = 3; diff --git a/logic/Preparation/Utility/Transformation.cs b/logic/Preparation/Utility/Transformation.cs index e5ad6fd..3e198ce 100644 --- a/logic/Preparation/Utility/Transformation.cs +++ b/logic/Preparation/Utility/Transformation.cs @@ -55,6 +55,8 @@ namespace Preparation.Utility return Protobuf.PropType.ShieldOrSpear; case Preparation.Utility.PropType.RecoveryFromDizziness: return Protobuf.PropType.RecoveryFromDizziness; + case PropType.CraftingBench: + return Protobuf.PropType.CraftingBench; case Preparation.Utility.PropType.Key3: return Protobuf.PropType.Key3; case Preparation.Utility.PropType.Key5: