Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
N
Neos
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
love_飞影
Neos
Commits
05e8030a
Commit
05e8030a
authored
May 26, 2023
by
timel
Committed by
Chunchi Che
May 28, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: trigger move from move.ts derectly
parent
d028c48c
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
62 additions
and
75 deletions
+62
-75
src/env.d.ts
src/env.d.ts
+1
-3
src/service/duel/move.ts
src/service/duel/move.ts
+29
-18
src/service/duel/selectIdleCmd.ts
src/service/duel/selectIdleCmd.ts
+8
-0
src/service/duel/start.ts
src/service/duel/start.ts
+3
-2
src/stores/cardStore.ts
src/stores/cardStore.ts
+3
-3
src/ui/Duel/NewPlayMat/Card/index.tsx
src/ui/Duel/NewPlayMat/Card/index.tsx
+10
-25
src/ui/Duel/NewPlayMat/Card/springs/toDeck.ts
src/ui/Duel/NewPlayMat/Card/springs/toDeck.ts
+2
-6
src/ui/Duel/NewPlayMat/Card/springs/toGround.ts
src/ui/Duel/NewPlayMat/Card/springs/toGround.ts
+1
-2
src/ui/Duel/NewPlayMat/Card/springs/toHand.ts
src/ui/Duel/NewPlayMat/Card/springs/toHand.ts
+2
-13
src/ui/Duel/NewPlayMat/Card/springs/toOutside.ts
src/ui/Duel/NewPlayMat/Card/springs/toOutside.ts
+2
-2
src/ui/Duel/NewPlayMat/Card/springs/types.ts
src/ui/Duel/NewPlayMat/Card/springs/types.ts
+1
-1
No files found.
src/env.d.ts
View file @
05e8030a
...
@@ -12,11 +12,9 @@ interface ImportMeta {
...
@@ -12,11 +12,9 @@ interface ImportMeta {
readonly
env
:
ImportMetaEnv
;
readonly
env
:
ImportMetaEnv
;
}
}
// 定义一个全局的myExtraDeckCodes变量
declare
var
myExtraDeckCodes
:
number
[];
import
{
EventEmitter
}
from
"
eventemitter3
"
;
import
{
EventEmitter
}
from
"
eventemitter3
"
;
declare
global
{
declare
global
{
var
eventBus
:
EventEmitter
;
var
eventBus
:
EventEmitter
;
var
myExtraDeckCodes
:
number
[];
}
}
src/service/duel/move.ts
View file @
05e8030a
...
@@ -7,6 +7,7 @@ import { useConfig } from "@/config";
...
@@ -7,6 +7,7 @@ import { useConfig } from "@/config";
import
{
sleep
}
from
"
@/infra
"
;
import
{
sleep
}
from
"
@/infra
"
;
import
{
REASON_MATERIAL
}
from
"
../../common
"
;
import
{
REASON_MATERIAL
}
from
"
../../common
"
;
import
{
ReportEnum
}
from
"
@/ui/Duel/NewPlayMat/Card/springs/types
"
;
const
{
matStore
}
=
store
;
const
{
matStore
}
=
store
;
const
NeosConfig
=
useConfig
();
const
NeosConfig
=
useConfig
();
...
@@ -171,6 +172,21 @@ export default async (move: MsgMove) => {
...
@@ -171,6 +172,21 @@ export default async (move: MsgMove) => {
const
toZone
=
const
toZone
=
move
.
to
.
toArray
()[
1
]
===
undefined
?
ygopro
.
CardZone
.
TZONE
:
to
.
location
;
move
.
to
.
toArray
()[
1
]
===
undefined
?
ygopro
.
CardZone
.
TZONE
:
to
.
location
;
// log出来看看,后期删掉即可
(
async
()
=>
{
const
{
text
}
=
await
fetchCard
(
code
);
console
.
warn
(
"
move
"
,
text
.
name
,
ygopro
.
CardZone
[
fromZone
],
from
.
sequence
,
"
->
"
,
ygopro
.
CardZone
[
toZone
],
to
.
sequence
);
console
.
warn
(
"
overlay
"
,
from
.
overlay_sequence
,
to
.
overlay_sequence
);
})();
// 处理token
// 处理token
let
target
:
CardType
;
let
target
:
CardType
;
...
@@ -186,24 +202,6 @@ export default async (move: MsgMove) => {
...
@@ -186,24 +202,6 @@ export default async (move: MsgMove) => {
target
=
cardStore
.
at
(
fromZone
,
from
.
controler
,
from
.
sequence
);
target
=
cardStore
.
at
(
fromZone
,
from
.
controler
,
from
.
sequence
);
}
}
(
async
()
=>
{
const
{
text
}
=
await
fetchCard
(
code
);
console
.
warn
(
"
---
"
);
console
.
log
(
"
move
"
,
text
.
name
,
ygopro
.
CardZone
[
fromZone
],
from
.
sequence
,
"
->
"
,
ygopro
.
CardZone
[
toZone
],
to
.
sequence
);
console
.
log
(
"
over
"
,
from
.
overlay_sequence
,
to
.
overlay_sequence
);
console
.
log
({
fromCards
});
console
.
log
({
target
});
console
.
warn
(
"
---
"
);
})();
if
(
toZone
===
OVERLAY
)
{
if
(
toZone
===
OVERLAY
)
{
// 准备超量召唤,超量素材入栈
// 准备超量召唤,超量素材入栈
if
(
reason
==
REASON_MATERIAL
)
overlayStack
.
push
(
target
);
if
(
reason
==
REASON_MATERIAL
)
overlayStack
.
push
(
target
);
...
@@ -225,12 +223,25 @@ export default async (move: MsgMove) => {
...
@@ -225,12 +223,25 @@ export default async (move: MsgMove) => {
if
([
HAND
,
GRAVE
,
REMOVED
,
DECK
,
EXTRA
].
includes
(
toZone
))
if
([
HAND
,
GRAVE
,
REMOVED
,
DECK
,
EXTRA
].
includes
(
toZone
))
toCards
.
forEach
((
c
)
=>
c
.
sequence
>=
to
.
sequence
&&
c
.
sequence
++
);
toCards
.
forEach
((
c
)
=>
c
.
sequence
>=
to
.
sequence
&&
c
.
sequence
++
);
// 更新信息
target
.
zone
=
toZone
;
target
.
zone
=
toZone
;
target
.
controller
=
to
.
controler
;
target
.
controller
=
to
.
controler
;
target
.
sequence
=
to
.
sequence
;
target
.
sequence
=
to
.
sequence
;
target
.
code
=
code
;
target
.
code
=
code
;
target
.
position
=
to
.
position
;
target
.
position
=
to
.
position
;
// 维护完了之后,开始动画
eventBus
.
emit
(
ReportEnum
.
Move
,
target
.
uuid
);
// 如果from或者to是手卡,那么需要刷新除了这张卡之外,这个玩家的所有手卡
if
([
fromZone
,
toZone
].
includes
(
HAND
))
{
cardStore
.
at
(
HAND
,
target
.
controller
).
forEach
((
card
)
=>
{
if
(
card
.
uuid
!==
target
.
uuid
)
{
console
.
log
(
"
refresh hand
"
,
card
.
uuid
);
eventBus
.
emit
(
ReportEnum
.
Move
,
card
.
uuid
);
}
});
}
// 注意,一个monster的overlayMaterials中的每一项都是一个cardType,
// 注意,一个monster的overlayMaterials中的每一项都是一个cardType,
// 并且,overlayMaterials的idx就是超量素材的sequence。
// 并且,overlayMaterials的idx就是超量素材的sequence。
// 如果一个card的zone是OVERLAY,那么它本身的sequence项是无意义的。
// 如果一个card的zone是OVERLAY,那么它本身的sequence项是无意义的。
...
...
src/service/duel/selectIdleCmd.ts
View file @
05e8030a
...
@@ -41,6 +41,14 @@ export default (selectIdleCmd: MsgSelectIdleCmd) => {
...
@@ -41,6 +41,14 @@ export default (selectIdleCmd: MsgSelectIdleCmd) => {
interactType
,
interactType
,
response
:
data
.
response
,
response
:
data
.
response
,
});
});
console
.
log
(
"
idleTypeToInteractType
"
,
cardStore
.
at
(
location
,
player
)[
sequence
],
{
location
:
ygopro
.
CardZone
[
location
],
sequence
,
}
);
cardStore
.
at
(
location
,
player
)[
sequence
].
idleInteractivities
.
push
({
cardStore
.
at
(
location
,
player
)[
sequence
].
idleInteractivities
.
push
({
...
tmp
,
...
tmp
,
interactType
,
interactType
,
...
...
src/service/duel/start.ts
View file @
05e8030a
...
@@ -104,7 +104,6 @@ export default (start: ygopro.StocGameMessage.MsgStart) => {
...
@@ -104,7 +104,6 @@ export default (start: ygopro.StocGameMessage.MsgStart) => {
/** 自动从code推断出occupant */
/** 自动从code推断出occupant */
const
genCard
=
(
o
:
CardType
)
=>
{
const
genCard
=
(
o
:
CardType
)
=>
{
// FIXME 还没处理超量
const
t
=
proxy
(
o
);
const
t
=
proxy
(
o
);
subscribeKey
(
t
,
"
code
"
,
async
(
code
)
=>
{
subscribeKey
(
t
,
"
code
"
,
async
(
code
)
=>
{
const
{
text
,
data
}
=
await
fetchCard
(
code
??
0
);
const
{
text
,
data
}
=
await
fetchCard
(
code
??
0
);
...
@@ -115,6 +114,7 @@ export default (start: ygopro.StocGameMessage.MsgStart) => {
...
@@ -115,6 +114,7 @@ export default (start: ygopro.StocGameMessage.MsgStart) => {
};
};
const
TOKEN_SIZE
=
13
;
// 每人场上最多就只可能有13个token
const
TOKEN_SIZE
=
13
;
// 每人场上最多就只可能有13个token
let
uuid
=
0
;
const
cards
=
flatten
(
const
cards
=
flatten
(
[
[
start
.
deckSize1
,
start
.
deckSize1
,
...
@@ -126,7 +126,7 @@ export default (start: ygopro.StocGameMessage.MsgStart) => {
...
@@ -126,7 +126,7 @@ export default (start: ygopro.StocGameMessage.MsgStart) => {
].
map
((
length
,
i
)
=>
].
map
((
length
,
i
)
=>
Array
.
from
({
length
}).
map
((
_
,
sequence
)
=>
Array
.
from
({
length
}).
map
((
_
,
sequence
)
=>
genCard
({
genCard
({
// uuid: v4uuid()
,
uuid
:
uuid
++
,
code
:
0
,
code
:
0
,
controller
:
i
<
3
?
1
-
opponent
:
opponent
,
// 前3个是自己的卡组,后3个是对手的卡组
controller
:
i
<
3
?
1
-
opponent
:
opponent
,
// 前3个是自己的卡组,后3个是对手的卡组
originController
:
i
<
3
?
1
-
opponent
:
opponent
,
originController
:
i
<
3
?
1
-
opponent
:
opponent
,
...
@@ -142,6 +142,7 @@ export default (start: ygopro.StocGameMessage.MsgStart) => {
...
@@ -142,6 +142,7 @@ export default (start: ygopro.StocGameMessage.MsgStart) => {
text
:
{},
text
:
{},
isToken
:
!
((
i
+
1
)
%
3
),
isToken
:
!
((
i
+
1
)
%
3
),
overlayMaterials
:
[],
overlayMaterials
:
[],
position
:
ygopro
.
CardPosition
.
FACEDOWN
,
})
})
)
)
)
)
...
...
src/stores/cardStore.ts
View file @
05e8030a
...
@@ -7,14 +7,14 @@ import type { Interactivity } from "./matStore/types";
...
@@ -7,14 +7,14 @@ import type { Interactivity } from "./matStore/types";
* 以后会更名为 BlockState
* 以后会更名为 BlockState
*/
*/
export
interface
CardType
{
export
interface
CardType
{
// uuid: string; // FIXME 一张卡的唯一标识 一定需要这个吗?list的idx是不是就够了?
uuid
:
number
;
// 一张卡的唯一标识
code
:
number
;
code
:
number
;
// 卡号
data
:
CardData
;
data
:
CardData
;
text
:
CardText
;
text
:
CardText
;
controller
:
number
;
// 控制这个位置的玩家,0或1
controller
:
number
;
// 控制这个位置的玩家,0或1
originController
:
number
;
// 在卡组构建之中持有这张卡的玩家,方便reloadField的使用
originController
:
number
;
// 在卡组构建之中持有这张卡的玩家,方便reloadField的使用
zone
:
ygopro
.
CardZone
;
// 怪兽区/魔法陷阱区/手牌/卡组/墓地/除外区
zone
:
ygopro
.
CardZone
;
// 怪兽区/魔法陷阱区/手牌/卡组/墓地/除外区
position
?
:
ygopro
.
CardPosition
;
// 卡片的姿势:攻击还是守备
position
:
ygopro
.
CardPosition
;
// 卡片的姿势:攻击还是守备
sequence
:
number
;
// 卡片在区域中的序号
sequence
:
number
;
// 卡片在区域中的序号
idleInteractivities
:
Interactivity
<
number
>
[];
// IDLE状态下的互动信息
idleInteractivities
:
Interactivity
<
number
>
[];
// IDLE状态下的互动信息
placeInteractivity
?:
Interactivity
<
{
placeInteractivity
?:
Interactivity
<
{
...
...
src/ui/Duel/NewPlayMat/Card/index.tsx
View file @
05e8030a
import
React
,
{
useEffect
,
type
CSSProperties
,
type
FC
,
useState
}
from
"
react
"
;
import
React
,
{
useEffect
,
type
CSSProperties
,
type
FC
,
useState
}
from
"
react
"
;
import
{
cardStore
,
messageStore
,
CardType
}
from
"
@/stores
"
;
import
{
cardStore
,
messageStore
,
CardType
}
from
"
@/stores
"
;
import
"
./index.scss
"
;
import
"
./index.scss
"
;
import
{
useSnapshot
}
from
"
valtio
"
;
import
{
useSnapshot
,
subscribe
}
from
"
valtio
"
;
import
{
subscribeKey
}
from
"
valtio/utils
"
;
import
{
watch
}
from
"
valtio/utils
"
;
import
{
watch
}
from
"
valtio/utils
"
;
import
{
useSpring
,
animated
,
to
}
from
"
@react-spring/web
"
;
import
{
useSpring
,
animated
,
to
}
from
"
@react-spring/web
"
;
import
{
ygopro
}
from
"
@/api
"
;
import
{
ygopro
}
from
"
@/api
"
;
...
@@ -31,57 +32,41 @@ export const Card: FC<{ idx: number }> = React.memo(({ idx }) => {
...
@@ -31,57 +32,41 @@ export const Card: FC<{ idx: number }> = React.memo(({ idx }) => {
height
:
0
,
height
:
0
,
}));
}));
const
reload
=
(
zone
:
ygopro
.
CardZone
,
report
:
boolean
)
=>
{
const
reload
=
async
(
zone
:
ygopro
.
CardZone
)
=>
{
switch
(
zone
)
{
switch
(
zone
)
{
case
MZONE
:
case
MZONE
:
case
SZONE
:
case
SZONE
:
case
OVERLAY
:
case
OVERLAY
:
moveToGround
({
card
:
state
,
api
,
report
});
await
moveToGround
({
card
:
state
,
api
});
break
;
break
;
case
HAND
:
case
HAND
:
moveToHand
({
card
:
state
,
api
,
report
});
await
moveToHand
({
card
:
state
,
api
});
break
;
break
;
case
DECK
:
case
DECK
:
case
EXTRA
:
case
EXTRA
:
moveToDeck
({
card
:
state
,
api
,
report
});
await
moveToDeck
({
card
:
state
,
api
});
break
;
break
;
case
GRAVE
:
case
GRAVE
:
case
REMOVED
:
case
REMOVED
:
moveToOutside
({
card
:
state
,
api
,
report
});
await
moveToOutside
({
card
:
state
,
api
});
break
;
break
;
}
}
};
};
useEffect
(()
=>
{
useEffect
(()
=>
{
reload
(
state
.
zone
,
false
);
reload
(
state
.
zone
);
},
[]);
},
[]);
const
[
highlight
,
setHighlight
]
=
useState
(
false
);
const
[
highlight
,
setHighlight
]
=
useState
(
false
);
const
[
shadowOpacity
,
setShadowOpacity
]
=
useState
(
0
);
const
[
shadowOpacity
,
setShadowOpacity
]
=
useState
(
0
);
watch
((
get
)
=>
{
eventBus
.
on
(
ReportEnum
.
Move
,
(
uuid
)
=>
{
const
{
zone
,
sequence
,
controller
,
xyzMonster
,
idleInteractivities
}
=
if
(
uuid
===
state
.
uuid
)
reload
(
state
.
zone
);
get
(
state
);
reload
(
zone
,
true
);
});
});
useEffect
(()
=>
{
useEffect
(()
=>
{
setHighlight
(
!!
snap
.
idleInteractivities
.
length
);
setHighlight
(
!!
snap
.
idleInteractivities
.
length
);
},
[
snap
.
idleInteractivities
]);
},
[
snap
.
idleInteractivities
]);
// 在别的手卡更改时候,刷新这张手卡
eventBus
.
on
(
ReportEnum
.
ReloadHand
,
({
sequence
,
controller
}:
{
sequence
:
number
;
controller
:
number
})
=>
{
if
(
state
.
zone
===
HAND
&&
state
.
sequence
!==
sequence
&&
state
.
controller
===
controller
)
{
reload
(
state
.
zone
,
false
);
}
}
);
return
(
return
(
<
animated
.
div
<
animated
.
div
className=
{
classnames
(
"
mat-card
"
,
{
highlight
})
}
className=
{
classnames
(
"
mat-card
"
,
{
highlight
})
}
...
...
src/ui/Duel/NewPlayMat/Card/springs/toDeck.ts
View file @
05e8030a
...
@@ -25,12 +25,8 @@ const {
...
@@ -25,12 +25,8 @@ const {
const
{
HAND
,
GRAVE
,
REMOVED
,
DECK
,
EXTRA
,
MZONE
,
SZONE
,
TZONE
,
OVERLAY
}
=
const
{
HAND
,
GRAVE
,
REMOVED
,
DECK
,
EXTRA
,
MZONE
,
SZONE
,
TZONE
,
OVERLAY
}
=
ygopro
.
CardZone
;
ygopro
.
CardZone
;
export
const
moveToDeck
=
async
(
props
:
{
export
const
moveToDeck
=
async
(
props
:
{
card
:
CardType
;
api
:
SpringApi
})
=>
{
card
:
CardType
;
const
{
card
,
api
}
=
props
;
api
:
SpringApi
;
report
:
boolean
;
})
=>
{
const
{
card
,
api
,
report
}
=
props
;
// report
// report
const
{
zone
,
sequence
,
controller
,
xyzMonster
,
position
}
=
card
;
const
{
zone
,
sequence
,
controller
,
xyzMonster
,
position
}
=
card
;
...
...
src/ui/Duel/NewPlayMat/Card/springs/toGround.ts
View file @
05e8030a
...
@@ -27,9 +27,8 @@ const { HAND, GRAVE, REMOVED, DECK, EXTRA, MZONE, SZONE, TZONE, OVERLAY } =
...
@@ -27,9 +27,8 @@ const { HAND, GRAVE, REMOVED, DECK, EXTRA, MZONE, SZONE, TZONE, OVERLAY } =
export
const
moveToGround
=
async
(
props
:
{
export
const
moveToGround
=
async
(
props
:
{
card
:
CardType
;
card
:
CardType
;
api
:
SpringApi
;
api
:
SpringApi
;
report
:
boolean
;
})
=>
{
})
=>
{
const
{
card
,
api
,
report
}
=
props
;
const
{
card
,
api
}
=
props
;
// report
// report
const
{
zone
,
sequence
,
controller
,
xyzMonster
,
position
,
overlayMaterials
}
=
const
{
zone
,
sequence
,
controller
,
xyzMonster
,
position
,
overlayMaterials
}
=
card
;
card
;
...
...
src/ui/Duel/NewPlayMat/Card/springs/toHand.ts
View file @
05e8030a
...
@@ -24,20 +24,9 @@ const {
...
@@ -24,20 +24,9 @@ const {
const
{
HAND
,
GRAVE
,
REMOVED
,
DECK
,
EXTRA
,
MZONE
,
SZONE
,
TZONE
,
OVERLAY
}
=
const
{
HAND
,
GRAVE
,
REMOVED
,
DECK
,
EXTRA
,
MZONE
,
SZONE
,
TZONE
,
OVERLAY
}
=
ygopro
.
CardZone
;
ygopro
.
CardZone
;
export
const
moveToHand
=
async
(
props
:
{
export
const
moveToHand
=
async
(
props
:
{
card
:
CardType
;
api
:
SpringApi
})
=>
{
card
:
CardType
;
const
{
card
,
api
}
=
props
;
api
:
SpringApi
;
report
:
boolean
;
})
=>
{
const
{
card
,
api
,
report
}
=
props
;
const
{
zone
,
sequence
,
controller
}
=
card
;
const
{
zone
,
sequence
,
controller
}
=
card
;
// 得刷新除了这个卡以外所有的自己的手卡
if
(
report
)
{
eventBus
.
emit
(
ReportEnum
.
ReloadHand
,
{
controller
,
sequence
,
});
}
// 手卡会有很复杂的计算...
// 手卡会有很复杂的计算...
const
hand_circle_center_x
=
0
;
const
hand_circle_center_x
=
0
;
const
hand_circle_center_y
=
const
hand_circle_center_y
=
...
...
src/ui/Duel/NewPlayMat/Card/springs/toOutside.ts
View file @
05e8030a
...
@@ -27,9 +27,8 @@ const { HAND, GRAVE, REMOVED, DECK, EXTRA, MZONE, SZONE, TZONE, OVERLAY } =
...
@@ -27,9 +27,8 @@ const { HAND, GRAVE, REMOVED, DECK, EXTRA, MZONE, SZONE, TZONE, OVERLAY } =
export
const
moveToOutside
=
async
(
props
:
{
export
const
moveToOutside
=
async
(
props
:
{
card
:
CardType
;
card
:
CardType
;
api
:
SpringApi
;
api
:
SpringApi
;
report
:
boolean
;
})
=>
{
})
=>
{
const
{
card
,
api
,
report
}
=
props
;
const
{
card
,
api
}
=
props
;
// report
// report
const
{
zone
,
sequence
,
controller
,
xyzMonster
,
position
,
overlayMaterials
}
=
const
{
zone
,
sequence
,
controller
,
xyzMonster
,
position
,
overlayMaterials
}
=
card
;
card
;
...
@@ -46,5 +45,6 @@ export const moveToOutside = async (props: {
...
@@ -46,5 +45,6 @@ export const moveToOutside = async (props: {
z
:
0
,
z
:
0
,
height
:
BLOCK_HEIGHT_S
.
value
,
height
:
BLOCK_HEIGHT_S
.
value
,
rz
:
isMe
(
controller
)
?
0
:
180
,
rz
:
isMe
(
controller
)
?
0
:
180
,
ry
:
[
ygopro
.
CardPosition
.
FACEDOWN
].
includes
(
position
)
?
180
:
0
,
});
});
};
};
src/ui/Duel/NewPlayMat/Card/springs/types.ts
View file @
05e8030a
...
@@ -12,5 +12,5 @@ export type SpringApi = SpringRef<{
...
@@ -12,5 +12,5 @@ export type SpringApi = SpringRef<{
}
>
;
}
>
;
export
enum
ReportEnum
{
export
enum
ReportEnum
{
ReloadHand
=
"
reload-hand
"
,
Move
=
"
move
"
,
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment