Browse Source

Merge pull request #552 from shangfengh/new

feat:  adjust the CharacterType Klee and TechOtaku
tags/v0.1.0
Changli Tang GitHub 2 years ago
parent
commit
08be045458
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 511 additions and 199 deletions
  1. +3
    -2
      docs/游戏机制与平衡性调整更新草案.md
  2. +7
    -1
      docs/版本更新说明.md
  3. +53
    -52
      logic/Client/MainWindow.xaml.cs
  4. +13
    -0
      logic/GameClass/GameObj/Character/Character.BuffManager.cs
  5. +45
    -18
      logic/GameClass/GameObj/Character/Character.cs
  6. +29
    -0
      logic/GameClass/GameObj/GameObj.cs
  7. +2
    -2
      logic/GameClass/GameObj/Map/Door.cs
  8. +9
    -3
      logic/GameClass/GameObj/Map/Map.cs
  9. +6
    -17
      logic/GameClass/GameObj/Moveable.cs
  10. +1
    -2
      logic/GameClass/GameObj/ObjOfCharacter.cs
  11. +25
    -1
      logic/GameClass/GameObj/Prop/Item.cs
  12. +4
    -4
      logic/GameEngine/MoveEngine.cs
  13. +44
    -27
      logic/Gaming/ActionManager.cs
  14. +28
    -17
      logic/Gaming/AttackManager.cs
  15. +9
    -1
      logic/Gaming/CharacterManager.cs
  16. +1
    -1
      logic/Gaming/Game.cs
  17. +0
    -2
      logic/Gaming/PropManager.cs
  18. +142
    -25
      logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs
  19. +4
    -0
      logic/Gaming/SkillManager/SkillManager.PassiveSkill.cs
  20. +8
    -3
      logic/Gaming/SkillManager/SkillManager.cs
  21. +3
    -1
      logic/Preparation/Interface/ICharacter.cs
  22. +1
    -1
      logic/Preparation/Interface/IMoveable.cs
  23. +6
    -6
      logic/Preparation/Interface/IOccupation.cs
  24. +56
    -11
      logic/Preparation/Interface/ISkill.cs
  25. +6
    -0
      logic/Preparation/Utility/Debugger.cs
  26. +2
    -1
      logic/Preparation/Utility/EnumType.cs
  27. +2
    -1
      logic/Preparation/Utility/GameData.cs
  28. +2
    -0
      logic/Preparation/Utility/Transformation.cs

+ 3
- 2
docs/游戏机制与平衡性调整更新草案.md View File

@@ -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


+ 7
- 1
docs/版本更新说明.md View File

@@ -36,4 +36,10 @@

# 5月15日更新
- feat:Robot可用
- hotfix: 修复了移动相关的bug
- hotfix: 修复了移动相关的bug

# 最新更新
- feat:TechOtaku可用
- feat:Klee、Idol已调整
- fix:修复了InSpire会给Tricker加速的问题
- fix:修复了开锁门的bug

+ 53
- 52
logic/Client/MainWindow.xaml.cs View File

@@ -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;


+ 13
- 0
logic/GameClass/GameObj/Character/Character.BuffManager.cs View File

@@ -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


+ 45
- 18
logic/GameClass/GameObj/Character/Character.cs View File

@@ -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())


+ 29
- 0
logic/GameClass/GameObj/GameObj.cs View File

@@ -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;


+ 2
- 2
logic/GameClass/GameObj/Map/Door.cs View File

@@ -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;
}
}


+ 9
- 3
logic/GameClass/GameObj/Map/Map.cs View File

@@ -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)
{


+ 6
- 17
logic/GameClass/GameObj/Moveable.cs View File

@@ -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
{


+ 1
- 2
logic/GameClass/GameObj/ObjOfCharacter.cs View File

@@ -1,5 +1,4 @@
using Google.Protobuf.WellKnownTypes;
using Preparation.Interface;
using Preparation.Interface;
using Preparation.Utility;
using System.Threading;



+ 25
- 1
logic/GameClass/GameObj/Prop/Item.cs View File

@@ -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;
}


+ 4
- 4
logic/GameEngine/MoveEngine.cs View File

@@ -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);
}
}


+ 44
- 27
logic/Gaming/ActionManager.cs View File

@@ -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)
//{


+ 28
- 17
logic/Gaming/AttackManager.cs View File

@@ -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<IGameObj>();


+ 9
- 1
logic/Gaming/CharacterManager.cs View File

@@ -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;
}


+ 1
- 1
logic/Gaming/Game.cs View File

@@ -160,7 +160,7 @@ namespace Gaming
Character? player = gameMap.FindPlayerToAction(playerID);
if (player != null)
{
return actionManager.Stop(player);
return ActionManager.Stop(player);
}
return false;
}


+ 0
- 2
logic/Gaming/PropManager.cs View File

@@ -5,8 +5,6 @@ using Preparation.Utility;
using System;
using Timothy.FrameRateTask;
using GameEngine;
using System.Numerics;
using System.Reflection;

namespace Gaming
{


+ 142
- 25
logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs View File

@@ -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<int>(
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
(() =>
{


+ 4
- 0
logic/Gaming/SkillManager/SkillManager.PassiveSkill.cs View File

@@ -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));
}
}
}
}

+ 8
- 3
logic/Gaming/SkillManager/SkillManager.cs View File

@@ -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;
}


+ 3
- 1
logic/Preparation/Interface/ICharacter.cs View File

@@ -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();
}


+ 1
- 1
logic/Preparation/Interface/IMoveable.cs View File

@@ -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; }


+ 6
- 6
logic/Preparation/Interface/IOccupation.cs View File

@@ -70,8 +70,8 @@ namespace Preparation.Interface

public BulletType InitBullet => BulletType.CommonAttackOfGhost;

public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.JumpyBomb });
public List<PassiveSkillType> ListOfIPassiveSkill => new(new PassiveSkillType[] { });
public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.JumpyBomb, ActiveSkillType.SparksNSplash });
public List<PassiveSkillType> ListOfIPassiveSkill => new(new PassiveSkillType[] { PassiveSkillType.Lucky });

public double concealment = GameData.basicConcealment;
public double Concealment => concealment;
@@ -169,7 +169,7 @@ namespace Preparation.Interface
public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.Punish });
public List<PassiveSkillType> 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;


+ 56
- 11
logic/Preparation/Interface/ISkill.cs View File

@@ -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:


+ 6
- 0
logic/Preparation/Utility/Debugger.cs View File

@@ -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
}
}


+ 2
- 1
logic/Preparation/Utility/EnumType.cs View File

@@ -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,


+ 2
- 1
logic/Preparation/Utility/GameData.cs View File

@@ -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;


+ 2
- 0
logic/Preparation/Utility/Transformation.cs View File

@@ -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:


Loading…
Cancel
Save