Compare commits

...

35 Commits

Author SHA1 Message Date
genxium
d06cb18a08 Fixed inertia on jumping. 2023-01-21 11:11:48 +08:00
genxium
00816fb636 Minor update. 2023-01-21 10:41:38 +08:00
genxium
ff24bea055 Fixed fireball trigger. 2023-01-21 10:40:13 +08:00
genxium
56d66a128a Minor updates. 2023-01-20 23:44:26 +08:00
genxium
2f097dfec5 Added turn-around and dashing actual triggers. 2023-01-20 23:22:02 +08:00
genxium
ff48b47ecc Updated documentation for the plan of UDP secondary session. 2023-01-20 20:49:26 +08:00
genxium
7a0127b17d Updated README. 2023-01-20 14:32:38 +08:00
genxium
59c8427c70 Enhanced turn-around performance. 2023-01-20 11:29:27 +08:00
genxium
c357ebad3b Updated README again. 2023-01-19 22:19:40 +08:00
genxium
b2e1f7c2a6 Updated README. 2023-01-19 10:45:48 +08:00
genxium
9a8c32197e Added TurnAroundFramesToRecover. 2023-01-19 09:20:52 +08:00
genxium
a82a238ce9 Added frontend log for inspection of "onPeerInputFrameUpsync". 2023-01-18 22:43:10 +08:00
genxium
5b76c5bbfb Minor fix. 2023-01-18 18:03:54 +08:00
genxium
b81c470135 Drafted peer inputFrameUpsync broadcasting mechanism. 2023-01-18 17:53:58 +08:00
genxium
48074d48af Misc fixes for UI alignments. 2023-01-18 12:22:12 +08:00
genxium
342efc623c Made frontend landscape. 2023-01-17 23:35:23 +08:00
genxium
b8e757064d Further enhanced frontend input processing and fixed frame data logging. 2023-01-17 17:38:18 +08:00
genxium
71b9e72592 Minor fix. 2023-01-17 15:16:31 +08:00
genxium
21b48b7c0d Updated frontend input generation. 2023-01-17 13:07:26 +08:00
genxium
fbfca965e6 Minor update. 2023-01-17 12:49:49 +08:00
genxium
b27b567c77 Fixed frontend action triggers. 2023-01-17 12:48:51 +08:00
genxium
e9119530f1 Updated README for UDP discussion. 2023-01-16 23:25:40 +08:00
genxium
e6a4295773 Updated charts in README. 2023-01-15 17:43:02 +08:00
Wing
aa14529bf8 Merge pull request #19 from genxium/explosion
Drafted bullet explosion data structure.
2023-01-15 17:23:52 +08:00
genxium
84af0d1572 Drafted bullet explosion data structure. 2023-01-15 17:21:34 +08:00
genxium
16fb23c376 Updated charts and refs in README. 2023-01-14 23:06:45 +08:00
genxium
d1f8a58154 Updated README. 2023-01-14 09:35:56 +08:00
genxium
89c31e8944 Updated README. 2023-01-13 15:13:27 +08:00
genxium
45380d170f Fixed fireball rollback sync. 2023-01-13 14:55:56 +08:00
genxium
dd9c03404e Fixed fireball rollback mechanism. 2023-01-13 12:10:06 +08:00
genxium
29e402ea71 Integrated onwall movements to multiplayer battle. 2023-01-12 18:09:02 +08:00
genxium
b1e3d6525c Fixes for wall jumping. 2023-01-12 16:09:20 +08:00
genxium
845282db50 Minor fix. 2023-01-12 12:55:57 +08:00
genxium
71a5a7b727 Drafted anti-air attack for Monk. 2023-01-11 22:24:31 +08:00
genxium
934a495d47 Updates for fireball bullet. 2023-01-11 18:42:57 +08:00
96 changed files with 13083 additions and 6883 deletions

View File

@@ -47,3 +47,32 @@ renderFrameId | toApplyInputFrameId
..., ..., ..., 368 | 90
369, 370, 371, 372 | 91
373, 374, 375, ... | 92
# Would using UDP instead of TCP yield better synchronization performance?
Yes, but with non-trivial efforts.
## Neat advantage using UDP
Let's check an actual use case. As soon as an inputFrame becomes all-confirmed, the server should downsync it to all active players -- and upon reception loss of the packet containing this "all-confirmed downsync inputFrame" to a certain player, the server MUST retransmit another packet containing the same inputFrame to that player.
To apply UDP on this use case, additional `ack & retransmission mechanism` would be required, which is a moderately difficult task -- don't just pick a 3rd party lib using TCP flow-control alike `sliding window mechanism`, e.g. [RUDP](https://www.geeksforgeeks.org/reliable-user-datagram-protocol-rudp/)! Here's why.
Assume that the server is downsyncing `sequence of packets[#1, #2, #3, #4, #5, #6, #7, #8, #9, #10]`, when using TCP we get the advantage that each active player is guaranteed to receive that same sequence in the same order -- however in a bad, lossy network when `packet#2` got lost several times for a certain player whose reception window size is just 5, it has to wait for the arrival of `packet#2` at `[_, #3, #4, #5, #6]`, thus unable to process `[#7, #8, #9, #10]` which could contain `unpredictable inputFrame` while `#2` being `correct prediction` for that player.
That's so neat but still an advantage for using UDP! Yet if the TCP flow-control alike `sliding window mechanism` is employed on UDP, such advantage'd be compromised.
To summarize, if UDP is used we need
- an `ack & retransmission mechanism` built on top of it to guarantee reception of critical packets for active players, and
- reception order is not necessary to be reserved (mimic [markConfirmationIfApplicable](https://github.com/genxium/DelayNoMore/blob/v0.9.14/battle_srv/models/room.go#L1085) to maintain `lastAllConfirmedInputFrameId`), but
- TCP flow-control alike `sliding window mechanism` should be avoided to gain advantage over TCP.
## Additional hassles to care about using UDP
When using UDP, it's also necessary to verify authorization of each incoming packet, e.g. by simple time limited symmetric key, due to being connectionless.
## Why not hybrid?
Instead of replacing all use of TCP by UDP, it's more reasonable to keep using TCP for login and the "all-confirmed downsync inputFrames" from server to players (and possibly "upsync inputFrames" from player to server, but tradeoff on that remains to be discussed), while using a `UDP secondary session` for broadcasting inputFrames of each individual player asap (either using p2p or not) just for **better prediction performance**!
## How do you actually implement the `UDP secondary session`?
It's not a global consensus, but in practice many UDP communications are platform specific due to their paired asynchronous I/O choices, e.g. epoll in Linux and kqueue in BSD-ish. Of course there're many 3rd party higher level encapsulated tools for cross-platform use but that introduces extra debugging when things go wrong.
Therefore, the following plan doesn't assume use of any specific 3rd party encapsulation of UDP communication.
![UDP_secondary_session](./charts/UDPEssentials.jpg)

View File

@@ -1,25 +1,38 @@
# Preface
This project is a demo for a websocket-based rollback netcode inspired by [GGPO](https://github.com/pond3r/ggpo/blob/master/doc/README.md).
This project is a demo for a websocket-based rollback netcode inspired by [GGPO](https://github.com/pond3r/ggpo/blob/master/doc/README.md). As lots of feedbacks ask for a discussion on using UDP instead, I tried to summarize my personal opinion about it in [ConcerningEdgeCases](./ConcerningEdgeCases.md) -- not necessarily correct but that's indeed a question to face :)
_(the following gif is sped up to ~1.5x for file size reduction, kindly note that animations are resumed from a partial progress)_
The following video is recorded over INTERNET using an input delay of 4 frames and it feels SMOOTH when playing! Please also checkout these demo videos
- [source video of the first gif](https://pan.baidu.com/s/1ML6hNupaPHPJRd5rcTvQvw?pwd=8ruc)
- [phone v.s. PC over internet battle#1](https://pan.baidu.com/s/1NuGxuMwrV_jalcToyUZPLg?pwd=kfkr)
- [phone v.s. PC over internet battle#2](https://pan.baidu.com/s/1kMiFdwDHyJpZJ0GGU1Y3eA?pwd=46gd)
- [PC Wifi viewing Phone 4g](https://pan.baidu.com/s/1PJEtC9iB_fcabMWhbx2oAg?pwd=tp7k)
- [PC Wifi viewing Phone Wifi (over internet of course)](https://pan.baidu.com/s/108rvC1CcUdiQeMauXWsLJg?pwd=mn39)
![gif_demo](./charts/jump_sync_spedup.gif)
to see how this demo carries out a full 60fps synchronization with the help of _batched input upsync/downsync_ for satisfying network I/O performance.
Please also checkout [this demo video](https://pan.baidu.com/s/1Lmot9cb0pYylfUvC8G4fDg?pwd=ia97) to see how this demo carries out a full 60fps synchronization with the help of _batched input upsync/downsync_ for satisfying network I/O performance.
![gif_demo_1](./charts/internet_fireball_explosion_wallmove_spedup.gif)
The video mainly shows the following features.
- The backend receives inputs from frontend peers and broadcasts back for synchronization.
- The game is recovered for a player upon reconnection.
- Both backend(Golang) and frontend(JavaScript) execute collision detection and handle collision contacts by the same algorithm. The backend dynamics is togglable by [Room.BackendDynamicsEnabled](https://github.com/genxium/DelayNoMore/blob/v0.5.2/battle_srv/models/room.go#L813), but **when turned off the game couldn't support recovery upon reconnection**.
![gif_demo_2](./charts/jump_sync_spedup.gif)
All gifs are sped up to ~1.5x for file size reduction, kindly note that animations are resumed from a partial progress!
# Notable Features
- Backend dynamics toggle via [Room.BackendDynamicsEnabled](https://github.com/genxium/DelayNoMore/blob/v0.9.14/battle_srv/models/room.go#L786)
- Recovery upon reconnection (only if backend dynamics is ON)
- Automatically correction for "slow ticker", especially "active slow ticker" which is well-known to be a headache for input synchronization
- Frame data logging toggle for both frontend & backend, useful for debugging out of sync entities when developing new features
_(how input delay roughly works)_
![input_delay_intro](./charts/InputDelayIntro.jpg)
_(how rollback-and-chase in this project roughly works)_
_(how rollback-and-chase in this project roughly works, kindly note that by the current implementation, each frontend only maintains a `lastAllConfirmedInputFrameId` for all the other peers, because the backend only downsyncs all-confirmed inputFrames, see [markConfirmationIfApplicable](https://github.com/genxium/DelayNoMore/blob/v0.9.14/battle_srv/models/room.go#L1085) for more information -- if a serverless peer-to-peer communication is seriously needed here, consider porting [markConfirmationIfApplicable](https://github.com/genxium/DelayNoMore/blob/v0.9.14/battle_srv/models/room.go#L1085) into frontend for maintaining `lastAllConfirmedInputFrameId` under chaotic reception order of inputFrames from peers)_
![server_clients](./charts/ServerClients.jpg)
![rollback_and_chase_intro](./charts/RollbackAndChase.jpg)
(By use of [GopherJs](https://github.com/gopherjs/gopherjs), the frontend codes for dynamics are now automatically generated)
![floating_point_accumulation_err](./charts/AvoidingFloatingPointAccumulationErr.jpg)
# 1. Building & running
@@ -27,7 +40,8 @@ _(how rollback-and-chase in this project roughly works)_
## 1.1 Tools to install
### Backend
- [Command Line Tools for Xcode](https://developer.apple.com/download/all/?q=command%20line%20tools) (on OSX) or [TDM-GCC](https://jmeubank.github.io/tdm-gcc/download/) (on Windows) (a `make` executable mandatory)
- [Golang1.18.6](https://golang.org/dl/) (brought down to 1.18 for GopherJs support, mandatory, in China please try a mirror site like [that of ustc](https://mirrors.ustc.edu.cn/golang/))
- [Golang1.18.6](https://golang.org/dl/) (brought down to 1.18 for _GopherJs_ support, mandatory, in China please try a mirror site like [that of ustc](https://mirrors.ustc.edu.cn/golang/))
- [GopherJs1.18.0-beta1](https://github.com/gopherjs/gopherjs/tree/v1.18.0-beta1) (optional, only for developemnt)
- [MySQL 5.7](https://dev.mysql.com/downloads/windows/installer/5.7.html) (mandatory, for OSX not all versions of 5.7 can be found thus 5.7.24 is recommended)
- [Redis 3.0.503 or above](https://redis.io/download/) (mandatory)
- [skeema](https://www.skeema.io/) (optional, only for convenient MySQL schema provisioning)
@@ -60,7 +74,7 @@ user@proj-root/battle_srv/configs> cp -r ./configs.template ./configs
user@proj-root/frontend/assets/plugin_scripts> cp ./conf.js.template ./conf.js
```
## 1.2 Actual building & running
## 1.3 Actual building & running
### Backend
```
### The following command runs mysql-server in foreground, it's almost NEVER run in such a way, please find a proper way to run it for yourself
@@ -89,3 +103,11 @@ ErrFatal {"err": "MISCONF Redis is configured to save RDB snapshots, but
```
Just restart your `redis-server` process.
### 2.2 Why not show "PING value" on frontend display?
The most important reason for not showing "PING value" is simple: in most games the "PING value" is collected by a dedicated kernel thread which doesn't interfere the UI thread or the primary networking thread. As this demo primarily runs on browser by far, I don't have this capability easily.
Moreover, in practice I found that to spot sync anomalies, the following tools are much more useful than the "PING VALUE".
- Detection of [prediction mismatch on the frontend](https://github.com/genxium/DelayNoMore/blob/v0.9.19/frontend/assets/scripts/Map.js#L842).
- Detection of [type#1 forceConfirmation on the backend](https://github.com/genxium/DelayNoMore/blob/v0.9.19/battle_srv/models/room.go#L1246).
- Detection of [type#2 forceConfirmation on the backend](https://github.com/genxium/DelayNoMore/blob/v0.9.19/battle_srv/models/room.go#L1259).

View File

@@ -89,6 +89,7 @@ func setRouter(router *gin.Engine) {
router.StaticFS("/asset", http.Dir(filepath.Join(Conf.General.AppRoot, "asset")))
router.GET("/ping", f)
router.GET("/tsrht", ws.Serve)
router.GET("/tsrhtSecondary", ws.HandleSecondaryWsSessionForPlayer)
apiRouter := router.Group("/api")
{

View File

@@ -38,6 +38,10 @@ func toPbRoomDownsyncFrame(rdf *battle.RoomDownsyncFrame) *pb.RoomDownsyncFrame
BattleState: last.BattleState,
CharacterState: last.CharacterState,
InAir: last.InAir,
OnWall: last.OnWall,
OnWallNormX: last.OnWallNormX,
OnWallNormY: last.OnWallNormY,
CapturedByInertia: last.CapturedByInertia,
JoinIndex: last.JoinIndex,
BulletTeamId: last.BulletTeamId,
ChCollisionTeamId: last.ChCollisionTeamId,
@@ -52,62 +56,74 @@ func toPbRoomDownsyncFrame(rdf *battle.RoomDownsyncFrame) *pb.RoomDownsyncFrame
for i, last := range rdf.MeleeBullets {
pbBullet := &pb.MeleeBullet{
BulletLocalId: last.BulletLocalId,
OriginatedRenderFrameId: last.OriginatedRenderFrameId,
OffenderJoinIndex: last.OffenderJoinIndex,
BulletLocalId: last.BattleAttr.BulletLocalId,
OriginatedRenderFrameId: last.BattleAttr.OriginatedRenderFrameId,
OffenderJoinIndex: last.BattleAttr.OffenderJoinIndex,
TeamId: last.BattleAttr.TeamId,
StartupFrames: last.StartupFrames,
CancellableStFrame: last.CancellableStFrame,
CancellableEdFrame: last.CancellableEdFrame,
ActiveFrames: last.ActiveFrames,
StartupFrames: last.Bullet.StartupFrames,
CancellableStFrame: last.Bullet.CancellableStFrame,
CancellableEdFrame: last.Bullet.CancellableEdFrame,
ActiveFrames: last.Bullet.ActiveFrames,
HitStunFrames: last.HitStunFrames,
BlockStunFrames: last.BlockStunFrames,
PushbackVelX: last.PushbackVelX,
PushbackVelY: last.PushbackVelY,
Damage: last.Damage,
HitStunFrames: last.Bullet.HitStunFrames,
BlockStunFrames: last.Bullet.BlockStunFrames,
PushbackVelX: last.Bullet.PushbackVelX,
PushbackVelY: last.Bullet.PushbackVelY,
Damage: last.Bullet.Damage,
SelfLockVelX: last.SelfLockVelX,
SelfLockVelY: last.SelfLockVelY,
SelfLockVelX: last.Bullet.SelfLockVelX,
SelfLockVelY: last.Bullet.SelfLockVelY,
HitboxOffsetX: last.HitboxOffsetX,
HitboxOffsetY: last.HitboxOffsetY,
HitboxSizeX: last.HitboxSizeX,
HitboxSizeY: last.HitboxSizeY,
HitboxOffsetX: last.Bullet.HitboxOffsetX,
HitboxOffsetY: last.Bullet.HitboxOffsetY,
HitboxSizeX: last.Bullet.HitboxSizeX,
HitboxSizeY: last.Bullet.HitboxSizeY,
BlowUp: last.BlowUp,
TeamId: last.TeamId,
BlowUp: last.Bullet.BlowUp,
SpeciesId: last.Bullet.SpeciesId,
ExplosionFrames: last.Bullet.ExplosionFrames,
BlState: last.BlState,
FramesInBlState: last.FramesInBlState,
}
ret.MeleeBullets[i] = pbBullet
}
for i, last := range rdf.FireballBullets {
pbBullet := &pb.FireballBullet{
BulletLocalId: last.BulletLocalId,
OriginatedRenderFrameId: last.OriginatedRenderFrameId,
OffenderJoinIndex: last.OffenderJoinIndex,
BulletLocalId: last.BattleAttr.BulletLocalId,
OriginatedRenderFrameId: last.BattleAttr.OriginatedRenderFrameId,
OffenderJoinIndex: last.BattleAttr.OffenderJoinIndex,
TeamId: last.BattleAttr.TeamId,
StartupFrames: last.StartupFrames,
CancellableStFrame: last.CancellableStFrame,
CancellableEdFrame: last.CancellableEdFrame,
ActiveFrames: last.ActiveFrames,
StartupFrames: last.Bullet.StartupFrames,
CancellableStFrame: last.Bullet.CancellableStFrame,
CancellableEdFrame: last.Bullet.CancellableEdFrame,
ActiveFrames: last.Bullet.ActiveFrames,
HitStunFrames: last.HitStunFrames,
BlockStunFrames: last.BlockStunFrames,
PushbackVelX: last.PushbackVelX,
PushbackVelY: last.PushbackVelY,
Damage: last.Damage,
HitStunFrames: last.Bullet.HitStunFrames,
BlockStunFrames: last.Bullet.BlockStunFrames,
PushbackVelX: last.Bullet.PushbackVelX,
PushbackVelY: last.Bullet.PushbackVelY,
Damage: last.Bullet.Damage,
SelfLockVelX: last.SelfLockVelX,
SelfLockVelY: last.SelfLockVelY,
SelfLockVelX: last.Bullet.SelfLockVelX,
SelfLockVelY: last.Bullet.SelfLockVelY,
HitboxOffsetX: last.HitboxOffsetX,
HitboxOffsetY: last.HitboxOffsetY,
HitboxSizeX: last.HitboxSizeX,
HitboxSizeY: last.HitboxSizeY,
HitboxOffsetX: last.Bullet.HitboxOffsetX,
HitboxOffsetY: last.Bullet.HitboxOffsetY,
HitboxSizeX: last.Bullet.HitboxSizeX,
HitboxSizeY: last.Bullet.HitboxSizeY,
BlowUp: last.BlowUp,
TeamId: last.TeamId,
BlowUp: last.Bullet.BlowUp,
SpeciesId: last.Bullet.SpeciesId,
ExplosionFrames: last.Bullet.ExplosionFrames,
BlState: last.BlState,
FramesInBlState: last.FramesInBlState,
VirtualGridX: last.VirtualGridX,
VirtualGridY: last.VirtualGridY,
@@ -147,6 +163,10 @@ func toPbPlayers(modelInstances map[int32]*Player, withMetaInfo bool) []*pb.Play
BattleState: last.BattleState,
CharacterState: last.CharacterState,
InAir: last.InAir,
OnWall: last.OnWall,
OnWallNormX: last.OnWallNormX,
OnWallNormY: last.OnWallNormY,
CapturedByInertia: last.CapturedByInertia,
JoinIndex: last.JoinIndex,
BulletTeamId: last.BulletTeamId,
ChCollisionTeamId: last.ChCollisionTeamId,
@@ -195,6 +215,10 @@ func toJsPlayers(modelInstances map[int32]*Player) []*battle.PlayerDownsync {
MaxHp: last.MaxHp,
ColliderRadius: last.ColliderRadius,
InAir: last.InAir,
OnWall: last.OnWall,
OnWallNormX: last.OnWallNormX,
OnWallNormY: last.OnWallNormY,
CapturedByInertia: last.CapturedByInertia,
Score: last.Score,
Removed: last.Removed,
}

View File

@@ -27,10 +27,11 @@ const (
UPSYNC_MSG_ACT_PLAYER_CMD = int32(2)
UPSYNC_MSG_ACT_PLAYER_COLLIDER_ACK = int32(3)
DOWNSYNC_MSG_ACT_HB_REQ = int32(1)
DOWNSYNC_MSG_ACT_INPUT_BATCH = int32(2)
DOWNSYNC_MSG_ACT_BATTLE_STOPPED = int32(3)
DOWNSYNC_MSG_ACT_FORCED_RESYNC = int32(4)
DOWNSYNC_MSG_ACT_HB_REQ = int32(1)
DOWNSYNC_MSG_ACT_INPUT_BATCH = int32(2)
DOWNSYNC_MSG_ACT_BATTLE_STOPPED = int32(3)
DOWNSYNC_MSG_ACT_FORCED_RESYNC = int32(4)
DOWNSYNC_MSG_ACT_PEER_INPUT_BATCH = int32(5)
DOWNSYNC_MSG_ACT_BATTLE_READY_TO_START = int32(-1)
DOWNSYNC_MSG_ACT_BATTLE_START = int32(0)
@@ -116,10 +117,15 @@ type Room struct {
*
* Moreover, during the invocation of `PlayerSignalToCloseDict`, the `Player` instance is supposed to be deallocated (though not synchronously).
*/
PlayerDownsyncSessionDict map[int32]*websocket.Conn
PlayerDownsyncChanDict map[int32](chan pb.InputsBufferSnapshot)
PlayerDownsyncSessionDict map[int32]*websocket.Conn
PlayerSignalToCloseDict map[int32]SignalToCloseConnCbType
PlayerDownsyncChanDict map[int32](chan pb.InputsBufferSnapshot)
PlayerSecondaryDownsyncSessionDict map[int32]*websocket.Conn
PlayerSecondarySignalToCloseDict map[int32]SignalToCloseConnCbType
PlayerSecondaryDownsyncChanDict map[int32](chan pb.InputsBufferSnapshot)
PlayerActiveWatchdogDict map[int32](*Watchdog)
PlayerSignalToCloseDict map[int32]SignalToCloseConnCbType
Score float32
State int32
Index int
@@ -184,7 +190,7 @@ func (pR *Room) AddPlayerIfPossible(pPlayerFromDbInit *Player, session *websocke
pR.PlayerSignalToCloseDict[playerId] = signalToCloseConnOfThisPlayer
newWatchdog := NewWatchdog(ConstVals.Ws.WillKickIfInactiveFor, func() {
Logger.Warn("Conn inactive watchdog triggered#1:", zap.Any("playerId", playerId), zap.Any("roomId", pR.Id), zap.Any("roomState", pR.State), zap.Any("roomEffectivePlayerCount", pR.EffectivePlayerCount))
signalToCloseConnOfThisPlayer(Constants.RetCode.ActiveWatchdog, "")
pR.signalToCloseAllSessionsOfPlayer(playerId, Constants.RetCode.ActiveWatchdog)
})
newWatchdog.Stop()
pR.PlayerActiveWatchdogDict[playerId] = newWatchdog
@@ -221,7 +227,7 @@ func (pR *Room) ReAddPlayerIfPossible(pTmpPlayerInstance *Player, session *webso
pR.PlayerSignalToCloseDict[playerId] = signalToCloseConnOfThisPlayer
pR.PlayerActiveWatchdogDict[playerId] = NewWatchdog(ConstVals.Ws.WillKickIfInactiveFor, func() {
Logger.Warn("Conn inactive watchdog triggered#2:", zap.Any("playerId", playerId), zap.Any("roomId", pR.Id), zap.Any("roomState", pR.State), zap.Any("roomEffectivePlayerCount", pR.EffectivePlayerCount))
signalToCloseConnOfThisPlayer(Constants.RetCode.ActiveWatchdog, "")
pR.signalToCloseAllSessionsOfPlayer(playerId, Constants.RetCode.ActiveWatchdog)
}) // For ReAdded player the new watchdog starts immediately
Logger.Warn("ReAddPlayerIfPossible finished.", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("joinIndex", pEffectiveInRoomPlayerInstance.JoinIndex), zap.Any("playerBattleState", pEffectiveInRoomPlayerInstance.BattleState), zap.Any("roomState", pR.State), zap.Any("roomEffectivePlayerCount", pR.EffectivePlayerCount), zap.Any("AckingFrameId", pEffectiveInRoomPlayerInstance.AckingFrameId), zap.Any("AckingInputFrameId", pEffectiveInRoomPlayerInstance.AckingInputFrameId), zap.Any("LastSentInputFrameId", pEffectiveInRoomPlayerInstance.LastSentInputFrameId))
@@ -335,7 +341,20 @@ func (pR *Room) playerDownsyncStr(player *battle.PlayerDownsync) string {
if player.InAir {
inAirInt = 1
}
s := fmt.Sprintf("{%d,%d,%d,%d,%d,%d,%d}", player.JoinIndex, player.VirtualGridX, player.VirtualGridY, player.VelX, player.VelY, player.FramesToRecover, inAirInt)
onWallInt := 0
if player.OnWall {
onWallInt = 1
}
s := fmt.Sprintf("{%d,%d,%d,%d,%d,%d,%d,%d}", player.JoinIndex, player.VirtualGridX, player.VirtualGridY, player.VelX, player.VelY, player.FramesToRecover, inAirInt, onWallInt)
return s
}
func (pR *Room) fireballDownsyncStr(fireball *battle.FireballBullet) string {
if nil == fireball {
return ""
}
s := fmt.Sprintf("{%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d}", fireball.BattleAttr.BulletLocalId, fireball.BattleAttr.OriginatedRenderFrameId, fireball.BattleAttr.OffenderJoinIndex, fireball.VirtualGridX, fireball.VirtualGridY, fireball.VelX, fireball.VelY, fireball.DirX, fireball.DirY, fireball.Bullet.HitboxSizeX, fireball.Bullet.HitboxSizeY)
return s
}
@@ -365,7 +384,11 @@ func (pR *Room) rdfIdToActuallyUsedInputString() string {
for _, player := range rdf.PlayersArr {
playersStrBldr = append(playersStrBldr, pR.playerDownsyncStr(player))
}
s = append(s, fmt.Sprintf("rdfId:%d\nplayers:[%v]\nactuallyUsedinputList:{%v}", rdfId, strings.Join(playersStrBldr, ","), pR.inputFrameDownsyncStr(pR.rdfIdToActuallyUsedInput[rdfId])))
fireballsStrBldr := make([]string, 0, len(rdf.FireballBullets))
for _, fireball := range rdf.FireballBullets {
fireballsStrBldr = append(fireballsStrBldr, pR.fireballDownsyncStr(fireball))
}
s = append(s, fmt.Sprintf("rdfId:%d\nplayers:[%v]\nfireballs:[%v]\nactuallyUsedinputList:{%v}", rdfId, strings.Join(playersStrBldr, ","), strings.Join(fireballsStrBldr, ","), pR.inputFrameDownsyncStr(pR.rdfIdToActuallyUsedInput[rdfId])))
}
return strings.Join(s, "\n")
@@ -381,7 +404,7 @@ func (pR *Room) StartBattle() {
for _, player := range pR.Players {
speciesId := int(player.JoinIndex - 1) // FIXME: Hardcoded the values for now
if player.JoinIndex == 2 {
if player.JoinIndex == 1 {
speciesId = 4096
}
chosenCh := battle.Characters[speciesId]
@@ -465,7 +488,7 @@ func (pR *Room) StartBattle() {
kickoffFrameJs := pR.RenderFrameBuffer.GetByFrameId(0).(*battle.RoomDownsyncFrame)
pbKickOffRenderFrame := toPbRoomDownsyncFrame(kickoffFrameJs)
pbKickOffRenderFrame.SpeciesIdList = pR.SpeciesIdList
pR.sendSafely(pbKickOffRenderFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_START, playerId, true)
pR.sendSafely(pbKickOffRenderFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_START, playerId, true, MAGIC_JOIN_INDEX_DEFAULT)
}
Logger.Info(fmt.Sprintf("In `battleMainLoop` for roomId=%v sent out kickoffFrame", pR.Id))
}
@@ -492,7 +515,7 @@ func (pR *Room) StartBattle() {
}
}
downsyncLoop := func(playerId int32, player *Player, playerDownsyncChan chan pb.InputsBufferSnapshot) {
downsyncLoop := func(playerId int32, player *Player, playerDownsyncChan chan pb.InputsBufferSnapshot, playerSecondaryDownsyncChan chan pb.InputsBufferSnapshot) {
defer func() {
if r := recover(); r != nil {
Logger.Error("downsyncLoop, recovery spot#1, recovered from: ", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("panic", r))
@@ -500,19 +523,23 @@ func (pR *Room) StartBattle() {
Logger.Info(fmt.Sprintf("The `downsyncLoop` for (roomId=%v, playerId=%v) is stopped@renderFrameId=%v", pR.Id, playerId, pR.RenderFrameId))
}()
Logger.Debug(fmt.Sprintf("Started downsyncLoop for (roomId: %d, playerId:%d, playerDownsyncChan:%p)", pR.Id, playerId, playerDownsyncChan))
//Logger.Info(fmt.Sprintf("Started downsyncLoop for (roomId: %d, playerId:%d, playerDownsyncChan:%p)", pR.Id, playerId, playerDownsyncChan))
for {
nowBattleState := atomic.LoadInt32(&pR.State)
switch nowBattleState {
case RoomBattleStateIns.IDLE, RoomBattleStateIns.STOPPING_BATTLE_FOR_SETTLEMENT, RoomBattleStateIns.IN_SETTLEMENT, RoomBattleStateIns.IN_DISMISSAL:
Logger.Warn(fmt.Sprintf("Battle is not waiting/preparing/active for playerDownsyncChan for (roomId: %d, playerId:%d)", pR.Id, playerId))
return
}
select {
case inputsBufferSnapshot := <-playerDownsyncChan:
nowBattleState := atomic.LoadInt32(&pR.State)
switch nowBattleState {
case RoomBattleStateIns.IDLE, RoomBattleStateIns.STOPPING_BATTLE_FOR_SETTLEMENT, RoomBattleStateIns.IN_SETTLEMENT, RoomBattleStateIns.IN_DISMISSAL:
Logger.Warn(fmt.Sprintf("Battle is not waiting/preparing/active for playerDownsyncChan for (roomId: %d, playerId:%d)", pR.Id, playerId))
return
}
pR.downsyncToSinglePlayer(playerId, player, inputsBufferSnapshot.RefRenderFrameId, inputsBufferSnapshot.UnconfirmedMask, inputsBufferSnapshot.ToSendInputFrameDownsyncs, inputsBufferSnapshot.ShouldForceResync)
//Logger.Info(fmt.Sprintf("Sent inputsBufferSnapshot(refRenderFrameId:%d, unconfirmedMask:%v) to for (roomId: %d, playerId:%d)#2", inputsBufferSnapshot.RefRenderFrameId, inputsBufferSnapshot.UnconfirmedMask, pR.Id, playerId))
case inputsBufferSnapshot2 := <-playerSecondaryDownsyncChan:
pR.downsyncPeerInputFrameUpsyncToSinglePlayer(playerId, player, inputsBufferSnapshot2.ToSendInputFrameDownsyncs, inputsBufferSnapshot2.PeerJoinIndex)
//Logger.Info(fmt.Sprintf("Sent secondary inputsBufferSnapshot to for (roomId: %d, playerId:%d)#2", pR.Id, playerId))
default:
}
}
@@ -525,7 +552,8 @@ func (pR *Room) StartBattle() {
Each "playerDownsyncChan" stays alive through out the lifecycle of room instead of each "playerDownsyncSession", i.e. not closed or dereferenced upon disconnection.
*/
pR.PlayerDownsyncChanDict[playerId] = make(chan pb.InputsBufferSnapshot, pR.InputsBuffer.N)
go downsyncLoop(playerId, player, pR.PlayerDownsyncChanDict[playerId])
pR.PlayerSecondaryDownsyncChanDict[playerId] = make(chan pb.InputsBufferSnapshot, pR.InputsBuffer.N)
go downsyncLoop(playerId, player, pR.PlayerDownsyncChanDict[playerId], pR.PlayerSecondaryDownsyncChanDict[playerId])
}
pR.onBattlePrepare(func() {
@@ -582,6 +610,16 @@ func (pR *Room) OnBattleCmdReceived(pReq *pb.WsReq) {
inputsBufferSnapshot := pR.markConfirmationIfApplicable(inputFrameUpsyncBatch, playerId, player)
if nil != inputsBufferSnapshot {
pR.downsyncToAllPlayers(inputsBufferSnapshot)
} else {
// no new all-confirmed
toSendInputFrameDownsyncs := pR.cloneInputsBuffer(inputFrameUpsyncBatch[0].InputFrameId, inputFrameUpsyncBatch[len(inputFrameUpsyncBatch)-1].InputFrameId+1)
inputsBufferSnapshot = &pb.InputsBufferSnapshot{
ToSendInputFrameDownsyncs: toSendInputFrameDownsyncs,
PeerJoinIndex: player.JoinIndex,
}
//Logger.Info(fmt.Sprintf("OnBattleCmdReceived no new all-confirmed: roomId=%v, fromPlayerId=%v, forming peer broadcasting snapshot=%v", pR.Id, playerId, inputsBufferSnapshot))
pR.broadcastPeerUpsyncForBetterPrediction(inputsBufferSnapshot)
}
}
@@ -633,7 +671,7 @@ func (pR *Room) StopBattleForSettlement() {
PlayersArr: toPbPlayers(pR.Players, false),
CountdownNanos: -1, // TODO: Replace this magic constant!
}
pR.sendSafely(&assembledFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_STOPPED, playerId, true)
pR.sendSafely(&assembledFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_STOPPED, playerId, true, MAGIC_JOIN_INDEX_DEFAULT)
}
// Note that `pR.onBattleStoppedForSettlement` will be called by `battleMainLoop`.
}
@@ -662,7 +700,7 @@ func (pR *Room) onBattlePrepare(cb BattleStartCbType) {
Logger.Info("Sending out frame for RoomBattleState.PREPARE:", zap.Any("battleReadyToStartFrame", battleReadyToStartFrame))
for _, player := range pR.Players {
pR.sendSafely(battleReadyToStartFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_READY_TO_START, player.Id, true)
pR.sendSafely(battleReadyToStartFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_READY_TO_START, player.Id, true, MAGIC_JOIN_INDEX_DEFAULT)
}
battlePreparationNanos := int64(6000000000)
@@ -731,6 +769,7 @@ func (pR *Room) OnDismissed() {
pR.CharacterConfigsArr = make([]*battle.CharacterConfig, pR.Capacity)
pR.CollisionSysMap = make(map[int32]*resolv.Object)
pR.PlayerDownsyncSessionDict = make(map[int32]*websocket.Conn)
pR.PlayerSecondaryDownsyncSessionDict = make(map[int32]*websocket.Conn)
for _, oldWatchdog := range pR.PlayerActiveWatchdogDict {
oldWatchdog.Stop()
}
@@ -739,7 +778,12 @@ func (pR *Room) OnDismissed() {
close(oldChan)
}
pR.PlayerDownsyncChanDict = make(map[int32](chan pb.InputsBufferSnapshot))
for _, oldChan := range pR.PlayerSecondaryDownsyncChanDict {
close(oldChan)
}
pR.PlayerSecondaryDownsyncChanDict = make(map[int32](chan pb.InputsBufferSnapshot))
pR.PlayerSignalToCloseDict = make(map[int32]SignalToCloseConnCbType)
pR.PlayerSecondarySignalToCloseDict = make(map[int32]SignalToCloseConnCbType)
pR.JoinIndexBooleanArr = make([]bool, pR.Capacity)
pR.RenderCacheSize = 1024
pR.RenderFrameBuffer = battle.NewRingBuffer(pR.RenderCacheSize)
@@ -764,7 +808,7 @@ func (pR *Room) OnDismissed() {
pR.BattleDurationFrames = int32(60 * serverFps)
pR.BattleDurationNanos = int64(pR.BattleDurationFrames) * (pR.RollbackEstimatedDtNanos + 1)
pR.InputFrameUpsyncDelayTolerance = battle.ConvertToNoDelayInputFrameId(pR.NstDelayFrames) - 1 // this value should be strictly smaller than (NstDelayFrames >> InputScaleFrames), otherwise "type#1 forceConfirmation" might become a lag avalanche
pR.MaxChasingRenderFramesPerUpdate = 12 // Don't set this value too high to avoid exhausting frontend CPU within a single frame
pR.MaxChasingRenderFramesPerUpdate = 4 // Don't set this value too high to avoid exhausting frontend CPU within a single frame
pR.BackendDynamicsEnabled = true // [WARNING] When "false", recovery upon reconnection wouldn't work!
pR.ForceAllResyncOnAnyActiveSlowTicker = true // See tradeoff discussion in "downsyncToAllPlayers"
@@ -782,19 +826,24 @@ func (pR *Room) OnDismissed() {
}
func (pR *Room) expelPlayerDuringGame(playerId int32) {
if signalToCloseConnOfThisPlayer, existent := pR.PlayerSignalToCloseDict[playerId]; existent {
signalToCloseConnOfThisPlayer(Constants.RetCode.UnknownError, "") // TODO: Specify an error code
}
pR.signalToCloseAllSessionsOfPlayer(playerId, Constants.RetCode.UnknownError)
pR.onPlayerExpelledDuringGame(playerId)
}
func (pR *Room) expelPlayerForDismissal(playerId int32) {
if signalToCloseConnOfThisPlayer, existent := pR.PlayerSignalToCloseDict[playerId]; existent {
signalToCloseConnOfThisPlayer(Constants.RetCode.UnknownError, "") // TODO: Specify an error code
}
pR.signalToCloseAllSessionsOfPlayer(playerId, Constants.RetCode.UnknownError)
pR.onPlayerExpelledForDismissal(playerId)
}
func (pR *Room) signalToCloseAllSessionsOfPlayer(playerId int32, retCode int) {
if signalToCloseConnOfThisPlayer, existent := pR.PlayerSignalToCloseDict[playerId]; existent {
signalToCloseConnOfThisPlayer(retCode, "") // TODO: Specify an error code
}
if signalToCloseConnOfThisPlayer2, existent2 := pR.PlayerSecondarySignalToCloseDict[playerId]; existent2 {
signalToCloseConnOfThisPlayer2(retCode, "") // TODO: Specify an error code
}
}
func (pR *Room) onPlayerExpelledDuringGame(playerId int32) {
pR.onPlayerLost(playerId)
}
@@ -812,6 +861,10 @@ func (pR *Room) OnPlayerDisconnected(playerId int32) {
}
}()
if signalToCloseConnOfThisPlayer2, existent2 := pR.PlayerSecondarySignalToCloseDict[playerId]; existent2 {
signalToCloseConnOfThisPlayer2(Constants.RetCode.UnknownError, "") // TODO: Specify an error code
}
if player, existent := pR.Players[playerId]; existent {
thatPlayerBattleState := atomic.LoadInt32(&(player.BattleState))
switch thatPlayerBattleState {
@@ -871,6 +924,8 @@ func (pR *Room) clearPlayerNetworkSession(playerId int32) {
delete(pR.PlayerActiveWatchdogDict, playerId)
delete(pR.PlayerDownsyncSessionDict, playerId)
delete(pR.PlayerSignalToCloseDict, playerId)
delete(pR.PlayerSecondaryDownsyncSessionDict, playerId)
delete(pR.PlayerSecondarySignalToCloseDict, playerId)
}
}
@@ -960,7 +1015,7 @@ func (pR *Room) OnPlayerBattleColliderAcked(playerId int32) bool {
Logger.Debug(fmt.Sprintf("OnPlayerBattleColliderAcked-middle: roomId=%v, roomState=%v, targetPlayerId=%v, targetPlayerBattleState=%v, thatPlayerId=%v, thatPlayerBattleState=%v", pR.Id, pR.State, targetPlayer.Id, targetPlayer.BattleState, thatPlayer.Id, thatPlayerBattleState))
if thatPlayerId == targetPlayer.Id || (PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK == thatPlayerBattleState || PlayerBattleStateIns.ACTIVE == thatPlayerBattleState) {
Logger.Debug(fmt.Sprintf("OnPlayerBattleColliderAcked-sending DOWNSYNC_MSG_ACT_PLAYER_ADDED_AND_ACKED: roomId=%v, roomState=%v, targetPlayerId=%v, targetPlayerBattleState=%v, capacity=%v, EffectivePlayerCount=%v", pR.Id, pR.State, targetPlayer.Id, targetPlayer.BattleState, pR.Capacity, pR.EffectivePlayerCount))
pR.sendSafely(playerAckedFrame, nil, DOWNSYNC_MSG_ACT_PLAYER_ADDED_AND_ACKED, thatPlayer.Id, true)
pR.sendSafely(playerAckedFrame, nil, DOWNSYNC_MSG_ACT_PLAYER_ADDED_AND_ACKED, thatPlayer.Id, true, MAGIC_JOIN_INDEX_DEFAULT)
}
}
atomic.StoreInt32(&(targetPlayer.BattleState), PlayerBattleStateIns.ACTIVE)
@@ -993,28 +1048,43 @@ func (pR *Room) OnPlayerBattleColliderAcked(playerId int32) bool {
return true
}
func (pR *Room) sendSafely(roomDownsyncFrame *pb.RoomDownsyncFrame, toSendInputFrameDownsyncs []*pb.InputFrameDownsync, act int32, playerId int32, needLockExplicitly bool) {
func (pR *Room) sendSafely(roomDownsyncFrame *pb.RoomDownsyncFrame, toSendInputFrameDownsyncs []*pb.InputFrameDownsync, act int32, playerId int32, needLockExplicitly bool, peerJoinIndex int32) {
defer func() {
if r := recover(); r != nil {
Logger.Error("sendSafely, recovered from: ", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("panic", r))
}
}()
if playerDownsyncSession, existent := pR.PlayerDownsyncSessionDict[playerId]; existent {
pResp := &pb.WsResp{
Ret: int32(Constants.RetCode.Ok),
Act: act,
Rdf: roomDownsyncFrame,
InputFrameDownsyncBatch: toSendInputFrameDownsyncs,
}
pResp := &pb.WsResp{
Ret: int32(Constants.RetCode.Ok),
Act: act,
Rdf: roomDownsyncFrame,
InputFrameDownsyncBatch: toSendInputFrameDownsyncs,
PeerJoinIndex: peerJoinIndex,
}
theBytes, marshalErr := proto.Marshal(pResp)
if nil != marshalErr {
panic(fmt.Sprintf("Error marshaling downsync message: roomId=%v, playerId=%v, roomState=%v, roomEffectivePlayerCount=%v", pR.Id, playerId, pR.State, pR.EffectivePlayerCount))
}
theBytes, marshalErr := proto.Marshal(pResp)
if nil != marshalErr {
panic(fmt.Sprintf("Error marshaling downsync message: roomId=%v, playerId=%v, roomState=%v, roomEffectivePlayerCount=%v", pR.Id, playerId, pR.State, pR.EffectivePlayerCount))
}
if err := playerDownsyncSession.WriteMessage(websocket.BinaryMessage, theBytes); nil != err {
panic(fmt.Sprintf("Error sending downsync message: roomId=%v, playerId=%v, roomState=%v, roomEffectivePlayerCount=%v, err=%v", pR.Id, playerId, pR.State, pR.EffectivePlayerCount, err))
if MAGIC_JOIN_INDEX_DEFAULT == peerJoinIndex {
if playerDownsyncSession, existent := pR.PlayerDownsyncSessionDict[playerId]; existent {
if err := playerDownsyncSession.WriteMessage(websocket.BinaryMessage, theBytes); nil != err {
panic(fmt.Sprintf("Error sending primary downsync message: roomId=%v, playerId=%v, roomState=%v, roomEffectivePlayerCount=%v, err=%v", pR.Id, playerId, pR.State, pR.EffectivePlayerCount, err))
}
}
} else {
/*
[FIXME]
This branch is preferred to use an additional session of each player for sending, and the session is preferrably UDP instead of any TCP-based protocol, but I'm being lazy here.
See `<proj-root>/ConcerningEdgeCases.md` for the advantage of using UDP as a supplement.
*/
if playerSecondaryDownsyncSession, existent := pR.PlayerSecondaryDownsyncSessionDict[playerId]; existent {
if err := playerSecondaryDownsyncSession.WriteMessage(websocket.BinaryMessage, theBytes); nil != err {
panic(fmt.Sprintf("Error sending secondary downsync message: roomId=%v, playerId=%v, roomState=%v, roomEffectivePlayerCount=%v, err=%v", pR.Id, playerId, pR.State, pR.EffectivePlayerCount, err))
}
}
}
}
@@ -1325,11 +1395,35 @@ func (pR *Room) doBattleMainLoopPerTickBackendDynamicsWithProperLocking(prevRend
snapshotStFrameId = refSnapshotStFrameId
}
inputsBufferSnapshot := pR.produceInputsBufferSnapshotWithCurDynamicsRenderFrameAsRef(unconfirmedMask, snapshotStFrameId, pR.LastAllConfirmedInputFrameId+1)
Logger.Debug(fmt.Sprintf("[forceConfirmation] roomId=%v, room.RenderFrameId=%v, room.CurDynamicsRenderFrameId=%v, room.LastAllConfirmedInputFrameId=%v, unconfirmedMask=%v", pR.Id, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, pR.LastAllConfirmedInputFrameId, unconfirmedMask))
//Logger.Warn(fmt.Sprintf("[forceConfirmation] roomId=%v, room.RenderFrameId=%v, room.CurDynamicsRenderFrameId=%v, room.LastAllConfirmedInputFrameId=%v, unconfirmedMask=%v", pR.Id, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, pR.LastAllConfirmedInputFrameId, unconfirmedMask))
pR.downsyncToAllPlayers(inputsBufferSnapshot)
}
}
func (pR *Room) broadcastPeerUpsyncForBetterPrediction(inputsBufferSnapshot *pb.InputsBufferSnapshot) {
// See `<proj-root>/ConcerningEdgeCases.md` for why this method exists.
for _, player := range pR.PlayersArr {
playerBattleState := atomic.LoadInt32(&(player.BattleState))
switch playerBattleState {
case PlayerBattleStateIns.DISCONNECTED, PlayerBattleStateIns.LOST, PlayerBattleStateIns.EXPELLED_DURING_GAME, PlayerBattleStateIns.EXPELLED_IN_DISMISSAL, PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK, PlayerBattleStateIns.READDED_PENDING_BATTLE_COLLIDER_ACK:
continue
}
if player.JoinIndex == inputsBufferSnapshot.PeerJoinIndex {
continue
}
if playerSecondaryDownsyncChan, existent := pR.PlayerSecondaryDownsyncChanDict[player.Id]; existent {
/*
[FIXME]
This function is preferred to use an additional go-channel of each player for sending, see "downsyncLoop" & "Room.sendSafely" for more information!
*/
playerSecondaryDownsyncChan <- (*inputsBufferSnapshot)
} else {
Logger.Warn(fmt.Sprintf("playerDownsyncChan for (roomId: %d, playerId:%d) is gone", pR.Id, player.Id))
}
}
}
func (pR *Room) downsyncToAllPlayers(inputsBufferSnapshot *pb.InputsBufferSnapshot) {
/*
[WARNING] This function MUST BE called while "pR.InputsBufferLock" is LOCKED to **preserve the order of generation of "inputsBufferSnapshot" for sending** -- see comments in "OnBattleCmdReceived" and [this issue](https://github.com/genxium/DelayNoMore/issues/12).
@@ -1406,14 +1500,14 @@ func (pR *Room) downsyncToSinglePlayer(playerId int32, player *Player, refRender
We hereby assume that Golang runtime allocates & frees small amount of RAM quickly enough compared to either network I/O blocking in worst cases or the high frequency "per inputFrameDownsync*player" locking (though "OnBattleCmdReceived" locks at the same frequency but it's inevitable).
*/
playerJoinIndex := player.JoinIndex - 1
playerJoinIndexInBooleanArr := player.JoinIndex - 1
playerBattleState := atomic.LoadInt32(&(player.BattleState))
switch playerBattleState {
case PlayerBattleStateIns.DISCONNECTED, PlayerBattleStateIns.LOST, PlayerBattleStateIns.EXPELLED_DURING_GAME, PlayerBattleStateIns.EXPELLED_IN_DISMISSAL, PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK, PlayerBattleStateIns.READDED_PENDING_BATTLE_COLLIDER_ACK:
return
}
isSlowTicker := (0 < (unconfirmedMask & uint64(1<<uint32(playerJoinIndex))))
isSlowTicker := (0 < (unconfirmedMask & uint64(1<<uint32(playerJoinIndexInBooleanArr))))
shouldResync1 := (PlayerBattleStateIns.READDED_BATTLE_COLLIDER_ACKED == playerBattleState) // i.e. implies that "MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED == player.LastSentInputFrameId"
shouldResync2 := isSlowTicker // This condition is critical, if we don't send resync upon this condition, the "reconnected or slowly-clocking player" might never get its input synced
shouldResync3 := shouldForceResync
@@ -1438,13 +1532,13 @@ func (pR *Room) downsyncToSinglePlayer(playerId int32, player *Player, refRender
refRenderFrame.BackendUnconfirmedMask = unconfirmedMask
pbRefRenderFrame := toPbRoomDownsyncFrame(refRenderFrame)
pbRefRenderFrame.SpeciesIdList = pR.SpeciesIdList
pR.sendSafely(pbRefRenderFrame, toSendInputFrameDownsyncsSnapshot, DOWNSYNC_MSG_ACT_FORCED_RESYNC, playerId, false)
pR.sendSafely(pbRefRenderFrame, toSendInputFrameDownsyncsSnapshot, DOWNSYNC_MSG_ACT_FORCED_RESYNC, playerId, false, MAGIC_JOIN_INDEX_DEFAULT)
//Logger.Warn(fmt.Sprintf("Sent refRenderFrameId=%v & inputFrameIds [%d, %d), for roomId=%v, playerId=%d, playerJoinIndex=%d, renderFrameId=%d, curDynamicsRenderFrameId=%d, playerLastSentInputFrameId=%d: InputsBuffer=%v", refRenderFrameId, toSendInputFrameIdSt, toSendInputFrameIdEd, pR.Id, playerId, player.JoinIndex, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, player.LastSentInputFrameId, pR.InputsBufferString(false)))
if shouldResync1 {
Logger.Warn(fmt.Sprintf("Sent refRenderFrameId=%v & inputFrameIds [%d, %d), for roomId=%v, playerId=%d, playerJoinIndex=%d, renderFrameId=%d, curDynamicsRenderFrameId=%d, playerLastSentInputFrameId=%d: shouldResync1=%v, shouldResync2=%v, shouldResync3=%v, playerBattleState=%d", refRenderFrameId, toSendInputFrameIdSt, toSendInputFrameIdEd, pR.Id, playerId, player.JoinIndex, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, player.LastSentInputFrameId, shouldResync1, shouldResync2, shouldResync3, playerBattleState))
if shouldResync1 || shouldResync3 {
Logger.Debug(fmt.Sprintf("Sent refRenderFrameId=%v & inputFrameIds [%d, %d), for roomId=%v, playerId=%d, playerJoinIndex=%d, renderFrameId=%d, curDynamicsRenderFrameId=%d, playerLastSentInputFrameId=%d: shouldResync1=%v, shouldResync2=%v, shouldResync3=%v, playerBattleState=%d", refRenderFrameId, toSendInputFrameIdSt, toSendInputFrameIdEd, pR.Id, playerId, player.JoinIndex, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, player.LastSentInputFrameId, shouldResync1, shouldResync2, shouldResync3, playerBattleState))
}
} else {
pR.sendSafely(nil, toSendInputFrameDownsyncsSnapshot, DOWNSYNC_MSG_ACT_INPUT_BATCH, playerId, false)
pR.sendSafely(nil, toSendInputFrameDownsyncsSnapshot, DOWNSYNC_MSG_ACT_INPUT_BATCH, playerId, false, MAGIC_JOIN_INDEX_DEFAULT)
}
player.LastSentInputFrameId = toSendInputFrameIdEd - 1
if shouldResync1 {
@@ -1452,6 +1546,16 @@ func (pR *Room) downsyncToSinglePlayer(playerId int32, player *Player, refRender
}
}
func (pR *Room) downsyncPeerInputFrameUpsyncToSinglePlayer(playerId int32, player *Player, toSendInputFrameDownsyncsSnapshot []*pb.InputFrameDownsync, peerJoinIndex int32) {
playerBattleState := atomic.LoadInt32(&(player.BattleState))
switch playerBattleState {
case PlayerBattleStateIns.DISCONNECTED, PlayerBattleStateIns.LOST, PlayerBattleStateIns.EXPELLED_DURING_GAME, PlayerBattleStateIns.EXPELLED_IN_DISMISSAL, PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK, PlayerBattleStateIns.READDED_PENDING_BATTLE_COLLIDER_ACK:
return
}
pR.sendSafely(nil, toSendInputFrameDownsyncsSnapshot, DOWNSYNC_MSG_ACT_PEER_INPUT_BATCH, playerId, false, peerJoinIndex)
}
func (pR *Room) cloneInputsBuffer(stFrameId, edFrameId int32) []*pb.InputFrameDownsync {
// [WARNING] This function MUST BE called while "pR.InputsBufferLock" is locked!
cloned := make([]*pb.InputFrameDownsync, 0, edFrameId-stFrameId)
@@ -1484,3 +1588,22 @@ func (pR *Room) cloneInputsBuffer(stFrameId, edFrameId int32) []*pb.InputFrameDo
return cloned
}
func (pR *Room) SetSecondarySession(playerId int32, session *websocket.Conn, signalToCloseConnOfThisPlayer SignalToCloseConnCbType) {
// TODO: Use a dedicated lock
if player, ok := pR.Players[playerId]; ok {
playerBattleState := atomic.LoadInt32(&(player.BattleState))
switch playerBattleState {
case PlayerBattleStateIns.DISCONNECTED, PlayerBattleStateIns.LOST, PlayerBattleStateIns.EXPELLED_DURING_GAME, PlayerBattleStateIns.EXPELLED_IN_DISMISSAL:
// Kindly note that "PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK, PlayerBattleStateIns.READDED_PENDING_BATTLE_COLLIDER_ACK" are allowed
return
}
if _, existent := pR.PlayerDownsyncSessionDict[playerId]; existent {
if _, existent2 := pR.PlayerSecondaryDownsyncSessionDict[playerId]; !existent2 {
Logger.Info(fmt.Sprintf("SetSecondarySession for roomId=%v, playerId=%d, pR.Players=%v", pR.Id, playerId, pR.Players))
pR.PlayerSecondaryDownsyncSessionDict[playerId] = session
pR.PlayerSecondarySignalToCloseDict[playerId] = signalToCloseConnOfThisPlayer
}
}
}
}

View File

@@ -30,9 +30,9 @@ type PlayerDownsync struct {
VirtualGridX int32 `protobuf:"varint,2,opt,name=virtualGridX,proto3" json:"virtualGridX,omitempty"`
VirtualGridY int32 `protobuf:"varint,3,opt,name=virtualGridY,proto3" json:"virtualGridY,omitempty"`
DirX int32 `protobuf:"varint,4,opt,name=dirX,proto3" json:"dirX,omitempty"`
DirY int32 `protobuf:"varint,5,opt,name=dirY,proto3" json:"dirY,omitempty"` // "dirX" and "dirY" determines character facing
DirY int32 `protobuf:"varint,5,opt,name=dirY,proto3" json:"dirY,omitempty"`
VelX int32 `protobuf:"varint,6,opt,name=velX,proto3" json:"velX,omitempty"`
VelY int32 `protobuf:"varint,7,opt,name=velY,proto3" json:"velY,omitempty"` // "velX" and "velY" is used to record the accumulated effect by accelerations (including gravity)
VelY int32 `protobuf:"varint,7,opt,name=velY,proto3" json:"velY,omitempty"` // "velX" and "velY" is used to record the accumulated effect by inertia and accelerations (including gravity)
Speed int32 `protobuf:"varint,8,opt,name=speed,proto3" json:"speed,omitempty"` // this is the instantaneous scalar attribute of a character, different from but will be accounted in "velX" and "velY"
BattleState int32 `protobuf:"varint,9,opt,name=battleState,proto3" json:"battleState,omitempty"`
JoinIndex int32 `protobuf:"varint,10,opt,name=joinIndex,proto3" json:"joinIndex,omitempty"`
@@ -51,6 +51,10 @@ type PlayerDownsync struct {
FramesInvinsible int32 `protobuf:"varint,23,opt,name=framesInvinsible,proto3" json:"framesInvinsible,omitempty"`
BulletTeamId int32 `protobuf:"varint,24,opt,name=bulletTeamId,proto3" json:"bulletTeamId,omitempty"`
ChCollisionTeamId int32 `protobuf:"varint,25,opt,name=chCollisionTeamId,proto3" json:"chCollisionTeamId,omitempty"`
OnWall bool `protobuf:"varint,26,opt,name=onWall,proto3" json:"onWall,omitempty"` // like "inAir", its by design a standalone field only inferred by the collision result of "applyInputFrameDownsyncDynamicsOnSingleRenderFrame" instead of "characterState", because we need check the transition for "characterState" from this field, i.e. "onWall (prev -> curr)"
OnWallNormX int32 `protobuf:"varint,27,opt,name=onWallNormX,proto3" json:"onWallNormX,omitempty"`
OnWallNormY int32 `protobuf:"varint,28,opt,name=onWallNormY,proto3" json:"onWallNormY,omitempty"`
CapturedByInertia bool `protobuf:"varint,29,opt,name=capturedByInertia,proto3" json:"capturedByInertia,omitempty"` // like "inAir", its by design a standalone field only inferred by the calc result of "applyInputFrameDownsyncDynamicsOnSingleRenderFrame" instead of "characterState"
Name string `protobuf:"bytes,997,opt,name=name,proto3" json:"name,omitempty"`
DisplayName string `protobuf:"bytes,998,opt,name=displayName,proto3" json:"displayName,omitempty"`
Avatar string `protobuf:"bytes,999,opt,name=avatar,proto3" json:"avatar,omitempty"`
@@ -263,6 +267,34 @@ func (x *PlayerDownsync) GetChCollisionTeamId() int32 {
return 0
}
func (x *PlayerDownsync) GetOnWall() bool {
if x != nil {
return x.OnWall
}
return false
}
func (x *PlayerDownsync) GetOnWallNormX() int32 {
if x != nil {
return x.OnWallNormX
}
return 0
}
func (x *PlayerDownsync) GetOnWallNormY() int32 {
if x != nil {
return x.OnWallNormY
}
return 0
}
func (x *PlayerDownsync) GetCapturedByInertia() bool {
if x != nil {
return x.CapturedByInertia
}
return false
}
func (x *PlayerDownsync) GetName() string {
if x != nil {
return x.Name
@@ -362,6 +394,7 @@ type InputFrameUpsync struct {
InputFrameId int32 `protobuf:"varint,1,opt,name=inputFrameId,proto3" json:"inputFrameId,omitempty"`
Encoded uint64 `protobuf:"varint,2,opt,name=encoded,proto3" json:"encoded,omitempty"`
JoinIndex int32 `protobuf:"varint,3,opt,name=joinIndex,proto3" json:"joinIndex,omitempty"`
}
func (x *InputFrameUpsync) Reset() {
@@ -410,6 +443,13 @@ func (x *InputFrameUpsync) GetEncoded() uint64 {
return 0
}
func (x *InputFrameUpsync) GetJoinIndex() int32 {
if x != nil {
return x.JoinIndex
}
return 0
}
type InputFrameDownsync struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -634,6 +674,7 @@ type WsResp struct {
Rdf *RoomDownsyncFrame `protobuf:"bytes,4,opt,name=rdf,proto3" json:"rdf,omitempty"`
InputFrameDownsyncBatch []*InputFrameDownsync `protobuf:"bytes,5,rep,name=inputFrameDownsyncBatch,proto3" json:"inputFrameDownsyncBatch,omitempty"`
BciFrame *BattleColliderInfo `protobuf:"bytes,6,opt,name=bciFrame,proto3" json:"bciFrame,omitempty"`
PeerJoinIndex int32 `protobuf:"varint,7,opt,name=peerJoinIndex,proto3" json:"peerJoinIndex,omitempty"` // Only used when "InputsBufferSnapshot.peerJoinIndex" is used.
}
func (x *WsResp) Reset() {
@@ -710,6 +751,13 @@ func (x *WsResp) GetBciFrame() *BattleColliderInfo {
return nil
}
func (x *WsResp) GetPeerJoinIndex() int32 {
if x != nil {
return x.PeerJoinIndex
}
return 0
}
type InputsBufferSnapshot struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -719,6 +767,7 @@ type InputsBufferSnapshot struct {
UnconfirmedMask uint64 `protobuf:"varint,2,opt,name=unconfirmedMask,proto3" json:"unconfirmedMask,omitempty"`
ToSendInputFrameDownsyncs []*InputFrameDownsync `protobuf:"bytes,3,rep,name=toSendInputFrameDownsyncs,proto3" json:"toSendInputFrameDownsyncs,omitempty"`
ShouldForceResync bool `protobuf:"varint,4,opt,name=shouldForceResync,proto3" json:"shouldForceResync,omitempty"`
PeerJoinIndex int32 `protobuf:"varint,5,opt,name=peerJoinIndex,proto3" json:"peerJoinIndex,omitempty"` // Only used when "WsResp.peerJoinIndex" is used.
}
func (x *InputsBufferSnapshot) Reset() {
@@ -781,6 +830,13 @@ func (x *InputsBufferSnapshot) GetShouldForceResync() bool {
return false
}
func (x *InputsBufferSnapshot) GetPeerJoinIndex() int32 {
if x != nil {
return x.PeerJoinIndex
}
return 0
}
type MeleeBullet struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -807,6 +863,10 @@ type MeleeBullet struct {
BlowUp bool `protobuf:"varint,18,opt,name=blowUp,proto3" json:"blowUp,omitempty"`
TeamId int32 `protobuf:"varint,19,opt,name=teamId,proto3" json:"teamId,omitempty"`
BulletLocalId int32 `protobuf:"varint,20,opt,name=bulletLocalId,proto3" json:"bulletLocalId,omitempty"`
SpeciesId int32 `protobuf:"varint,21,opt,name=speciesId,proto3" json:"speciesId,omitempty"`
ExplosionFrames int32 `protobuf:"varint,22,opt,name=explosionFrames,proto3" json:"explosionFrames,omitempty"`
BlState int32 `protobuf:"varint,23,opt,name=blState,proto3" json:"blState,omitempty"`
FramesInBlState int32 `protobuf:"varint,24,opt,name=framesInBlState,proto3" json:"framesInBlState,omitempty"`
}
func (x *MeleeBullet) Reset() {
@@ -981,6 +1041,34 @@ func (x *MeleeBullet) GetBulletLocalId() int32 {
return 0
}
func (x *MeleeBullet) GetSpeciesId() int32 {
if x != nil {
return x.SpeciesId
}
return 0
}
func (x *MeleeBullet) GetExplosionFrames() int32 {
if x != nil {
return x.ExplosionFrames
}
return 0
}
func (x *MeleeBullet) GetBlState() int32 {
if x != nil {
return x.BlState
}
return 0
}
func (x *MeleeBullet) GetFramesInBlState() int32 {
if x != nil {
return x.FramesInBlState
}
return 0
}
type FireballBullet struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -1006,6 +1094,10 @@ type FireballBullet struct {
BlowUp bool `protobuf:"varint,18,opt,name=blowUp,proto3" json:"blowUp,omitempty"`
TeamId int32 `protobuf:"varint,19,opt,name=teamId,proto3" json:"teamId,omitempty"`
BulletLocalId int32 `protobuf:"varint,20,opt,name=bulletLocalId,proto3" json:"bulletLocalId,omitempty"`
SpeciesId int32 `protobuf:"varint,21,opt,name=speciesId,proto3" json:"speciesId,omitempty"`
ExplosionFrames int32 `protobuf:"varint,22,opt,name=explosionFrames,proto3" json:"explosionFrames,omitempty"`
BlState int32 `protobuf:"varint,23,opt,name=blState,proto3" json:"blState,omitempty"`
FramesInBlState int32 `protobuf:"varint,24,opt,name=framesInBlState,proto3" json:"framesInBlState,omitempty"`
VirtualGridX int32 `protobuf:"varint,999,opt,name=virtualGridX,proto3" json:"virtualGridX,omitempty"`
VirtualGridY int32 `protobuf:"varint,1000,opt,name=virtualGridY,proto3" json:"virtualGridY,omitempty"`
DirX int32 `protobuf:"varint,1001,opt,name=dirX,proto3" json:"dirX,omitempty"`
@@ -1187,6 +1279,34 @@ func (x *FireballBullet) GetBulletLocalId() int32 {
return 0
}
func (x *FireballBullet) GetSpeciesId() int32 {
if x != nil {
return x.SpeciesId
}
return 0
}
func (x *FireballBullet) GetExplosionFrames() int32 {
if x != nil {
return x.ExplosionFrames
}
return 0
}
func (x *FireballBullet) GetBlState() int32 {
if x != nil {
return x.BlState
}
return 0
}
func (x *FireballBullet) GetFramesInBlState() int32 {
if x != nil {
return x.FramesInBlState
}
return 0
}
func (x *FireballBullet) GetVirtualGridX() int32 {
if x != nil {
return x.VirtualGridX
@@ -1504,7 +1624,7 @@ var file_room_downsync_frame_proto_rawDesc = []byte{
0x0a, 0x19, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x5f,
0x66, 0x72, 0x61, 0x6d, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x73, 0x1a, 0x0e, 0x67, 0x65, 0x6f, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x22, 0xe9, 0x06, 0x0a, 0x0e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x6f,
0x6f, 0x74, 0x6f, 0x22, 0xf3, 0x07, 0x0a, 0x0e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x6f,
0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61,
0x6c, 0x47, 0x72, 0x69, 0x64, 0x58, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x76, 0x69,
@@ -1553,136 +1673,160 @@ var file_room_downsync_frame_proto_rawDesc = []byte{
0x28, 0x05, 0x52, 0x0c, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x54, 0x65, 0x61, 0x6d, 0x49, 0x64,
0x12, 0x2c, 0x0a, 0x11, 0x63, 0x68, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x54,
0x65, 0x61, 0x6d, 0x49, 0x64, 0x18, 0x19, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x63, 0x68, 0x43,
0x6f, 0x6c, 0x6c, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x13,
0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0xe5, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61,
0x6d, 0x65, 0x18, 0xe6, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c,
0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x17, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72,
0x18, 0xe7, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x22,
0x6f, 0x0a, 0x11, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x63,
0x6f, 0x64, 0x65, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x64, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
0x52, 0x02, 0x64, 0x78, 0x12, 0x0e, 0x0a, 0x02, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05,
0x52, 0x02, 0x64, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x74, 0x6e, 0x41, 0x4c, 0x65, 0x76, 0x65,
0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x62, 0x74, 0x6e, 0x41, 0x4c, 0x65, 0x76,
0x65, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x74, 0x6e, 0x42, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x18,
0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x62, 0x74, 0x6e, 0x42, 0x4c, 0x65, 0x76, 0x65, 0x6c,
0x22, 0x50, 0x0a, 0x10, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70,
0x73, 0x79, 0x6e, 0x63, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61,
0x6d, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x69, 0x6e, 0x70, 0x75,
0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x63, 0x6f,
0x64, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x65, 0x6e, 0x63, 0x6f, 0x64,
0x65, 0x64, 0x22, 0x7c, 0x0a, 0x12, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75,
0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c,
0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09,
0x69, 0x6e, 0x70, 0x75, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x52,
0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x63, 0x6f,
0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28,
0x04, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4c, 0x69, 0x73, 0x74,
0x22, 0x3b, 0x0a, 0x0f, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70, 0x73,
0x79, 0x6e, 0x63, 0x12, 0x28, 0x0a, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d,
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x6c,
0x69, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0xb8, 0x02,
0x0a, 0x05, 0x57, 0x73, 0x52, 0x65, 0x71, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x1a, 0x0a,
0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74,
0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x61, 0x63, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6a,
0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09,
0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x63, 0x6b,
0x69, 0x6e, 0x67, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05,
0x52, 0x0d, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12,
0x2e, 0x0a, 0x12, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72,
0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x61, 0x63, 0x6b,
0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12,
0x4e, 0x0a, 0x15, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73,
0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61,
0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x15, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46,
0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12,
0x27, 0x0a, 0x02, 0x68, 0x62, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70,
0x73, 0x79, 0x6e, 0x63, 0x52, 0x02, 0x68, 0x62, 0x22, 0x89, 0x02, 0x0a, 0x06, 0x57, 0x73, 0x52,
0x65, 0x73, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
0x52, 0x03, 0x72, 0x65, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x63, 0x68, 0x6f, 0x65, 0x64, 0x4d,
0x73, 0x67, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x65, 0x63, 0x68, 0x6f,
0x65, 0x64, 0x4d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03,
0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x61, 0x63, 0x74, 0x12, 0x2b, 0x0a, 0x03, 0x72, 0x64, 0x66,
0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d,
0x65, 0x52, 0x03, 0x72, 0x64, 0x66, 0x12, 0x54, 0x0a, 0x17, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46,
0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63,
0x68, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73,
0x79, 0x6e, 0x63, 0x52, 0x17, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44,
0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x36, 0x0a, 0x08,
0x62, 0x63, 0x69, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f,
0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x62, 0x63, 0x69, 0x46,
0x72, 0x61, 0x6d, 0x65, 0x22, 0xf4, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x42,
0x75, 0x66, 0x66, 0x65, 0x72, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x2a, 0x0a,
0x10, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6e, 0x64,
0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x0f, 0x75, 0x6e, 0x63,
0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01,
0x28, 0x04, 0x52, 0x0f, 0x75, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4d,
0x61, 0x73, 0x6b, 0x12, 0x58, 0x0a, 0x19, 0x74, 0x6f, 0x53, 0x65, 0x6e, 0x64, 0x49, 0x6e, 0x70,
0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x73,
0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79,
0x6e, 0x63, 0x52, 0x19, 0x74, 0x6f, 0x53, 0x65, 0x6e, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46,
0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x73, 0x12, 0x2c, 0x0a,
0x11, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x79,
0x6e, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64,
0x46, 0x6f, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x79, 0x6e, 0x63, 0x22, 0xfd, 0x05, 0x0a, 0x0b,
0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x12, 0x38, 0x0a, 0x17, 0x6f,
0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46,
0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x17, 0x6f, 0x72,
0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72,
0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x11, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65,
0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05,
0x52, 0x11, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e,
0x64, 0x65, 0x78, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x46, 0x72,
0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x73, 0x74, 0x61, 0x72,
0x74, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x63, 0x61, 0x6e,
0x63, 0x65, 0x6c, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x18,
0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x61, 0x62,
0x6c, 0x65, 0x53, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x12, 0x63, 0x61, 0x6e,
0x63, 0x65, 0x6c, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x18,
0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x61, 0x62,
0x6c, 0x65, 0x45, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x63, 0x74,
0x69, 0x76, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52,
0x0c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x24, 0x0a,
0x0d, 0x68, 0x69, 0x74, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x07,
0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x68, 0x69, 0x74, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61,
0x6d, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x6e,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x62, 0x6c,
0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x22, 0x0a,
0x0c, 0x70, 0x75, 0x73, 0x68, 0x62, 0x61, 0x63, 0x6b, 0x56, 0x65, 0x6c, 0x58, 0x18, 0x09, 0x20,
0x01, 0x28, 0x05, 0x52, 0x0c, 0x70, 0x75, 0x73, 0x68, 0x62, 0x61, 0x63, 0x6b, 0x56, 0x65, 0x6c,
0x58, 0x12, 0x22, 0x0a, 0x0c, 0x70, 0x75, 0x73, 0x68, 0x62, 0x61, 0x63, 0x6b, 0x56, 0x65, 0x6c,
0x59, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x70, 0x75, 0x73, 0x68, 0x62, 0x61, 0x63,
0x6b, 0x56, 0x65, 0x6c, 0x59, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x61, 0x6d, 0x61, 0x67, 0x65, 0x18,
0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x64, 0x61, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x22, 0x0a,
0x0c, 0x73, 0x65, 0x6c, 0x66, 0x4c, 0x6f, 0x63, 0x6b, 0x56, 0x65, 0x6c, 0x58, 0x18, 0x0c, 0x20,
0x01, 0x28, 0x05, 0x52, 0x0c, 0x73, 0x65, 0x6c, 0x66, 0x4c, 0x6f, 0x63, 0x6b, 0x56, 0x65, 0x6c,
0x58, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x65, 0x6c, 0x66, 0x4c, 0x6f, 0x63, 0x6b, 0x56, 0x65, 0x6c,
0x59, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x73, 0x65, 0x6c, 0x66, 0x4c, 0x6f, 0x63,
0x6b, 0x56, 0x65, 0x6c, 0x59, 0x12, 0x24, 0x0a, 0x0d, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x4f,
0x66, 0x66, 0x73, 0x65, 0x74, 0x58, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x68, 0x69,
0x74, 0x62, 0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x58, 0x12, 0x24, 0x0a, 0x0d, 0x68,
0x69, 0x74, 0x62, 0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x59, 0x18, 0x0f, 0x20, 0x01,
0x28, 0x05, 0x52, 0x0d, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74,
0x59, 0x12, 0x20, 0x0a, 0x0b, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x58,
0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x53, 0x69,
0x7a, 0x65, 0x58, 0x12, 0x20, 0x0a, 0x0b, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x53, 0x69, 0x7a,
0x65, 0x59, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78,
0x53, 0x69, 0x7a, 0x65, 0x59, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x6c, 0x6f, 0x77, 0x55, 0x70, 0x18,
0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x62, 0x6c, 0x6f, 0x77, 0x55, 0x70, 0x12, 0x16, 0x0a,
0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x74,
0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x4c,
0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x62, 0x75,
0x6c, 0x6c, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x22, 0xb5, 0x07, 0x0a, 0x0e,
0x6f, 0x6c, 0x6c, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x16,
0x0a, 0x06, 0x6f, 0x6e, 0x57, 0x61, 0x6c, 0x6c, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06,
0x6f, 0x6e, 0x57, 0x61, 0x6c, 0x6c, 0x12, 0x20, 0x0a, 0x0b, 0x6f, 0x6e, 0x57, 0x61, 0x6c, 0x6c,
0x4e, 0x6f, 0x72, 0x6d, 0x58, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6f, 0x6e, 0x57,
0x61, 0x6c, 0x6c, 0x4e, 0x6f, 0x72, 0x6d, 0x58, 0x12, 0x20, 0x0a, 0x0b, 0x6f, 0x6e, 0x57, 0x61,
0x6c, 0x6c, 0x4e, 0x6f, 0x72, 0x6d, 0x59, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6f,
0x6e, 0x57, 0x61, 0x6c, 0x6c, 0x4e, 0x6f, 0x72, 0x6d, 0x59, 0x12, 0x2c, 0x0a, 0x11, 0x63, 0x61,
0x70, 0x74, 0x75, 0x72, 0x65, 0x64, 0x42, 0x79, 0x49, 0x6e, 0x65, 0x72, 0x74, 0x69, 0x61, 0x18,
0x1d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x63, 0x61, 0x70, 0x74, 0x75, 0x72, 0x65, 0x64, 0x42,
0x79, 0x49, 0x6e, 0x65, 0x72, 0x74, 0x69, 0x61, 0x12, 0x13, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
0x18, 0xe5, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a,
0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0xe6, 0x07, 0x20,
0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65,
0x12, 0x17, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0xe7, 0x07, 0x20, 0x01, 0x28,
0x09, 0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x22, 0x6f, 0x0a, 0x11, 0x49, 0x6e, 0x70,
0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x12, 0x0e,
0x0a, 0x02, 0x64, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x64, 0x78, 0x12, 0x0e,
0x0a, 0x02, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x64, 0x79, 0x12, 0x1c,
0x0a, 0x09, 0x62, 0x74, 0x6e, 0x41, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28,
0x05, 0x52, 0x09, 0x62, 0x74, 0x6e, 0x41, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1c, 0x0a, 0x09,
0x62, 0x74, 0x6e, 0x42, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52,
0x09, 0x62, 0x74, 0x6e, 0x42, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x6e, 0x0a, 0x10, 0x49, 0x6e,
0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x22,
0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x01,
0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x18, 0x02, 0x20,
0x01, 0x28, 0x04, 0x52, 0x07, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x09,
0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x7c, 0x0a, 0x12, 0x49, 0x6e,
0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63,
0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61,
0x6d, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x4c, 0x69, 0x73,
0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x52, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x4c, 0x69,
0x73, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4c,
0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69,
0x72, 0x6d, 0x65, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x3b, 0x0a, 0x0f, 0x48, 0x65, 0x61, 0x72,
0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x28, 0x0a, 0x0f, 0x63,
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01,
0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65,
0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0xb8, 0x02, 0x0a, 0x05, 0x57, 0x73, 0x52, 0x65, 0x71, 0x12,
0x14, 0x0a, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05,
0x6d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49,
0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49,
0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03,
0x61, 0x63, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78,
0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65,
0x78, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x49, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x12, 0x61, 0x63, 0x6b, 0x69, 0x6e,
0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x06, 0x20,
0x01, 0x28, 0x05, 0x52, 0x12, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x4e, 0x0a, 0x15, 0x69, 0x6e, 0x70, 0x75, 0x74,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68,
0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63,
0x52, 0x15, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79,
0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x27, 0x0a, 0x02, 0x68, 0x62, 0x18, 0x08, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61,
0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x02, 0x68, 0x62,
0x22, 0xaf, 0x02, 0x0a, 0x06, 0x57, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x72,
0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x72, 0x65, 0x74, 0x12, 0x20, 0x0a,
0x0b, 0x65, 0x63, 0x68, 0x6f, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01,
0x28, 0x05, 0x52, 0x0b, 0x65, 0x63, 0x68, 0x6f, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x49, 0x64, 0x12,
0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x61, 0x63,
0x74, 0x12, 0x2b, 0x0a, 0x03, 0x72, 0x64, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e,
0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x03, 0x72, 0x64, 0x66, 0x12, 0x54,
0x0a, 0x17, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e,
0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72,
0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x17, 0x69, 0x6e, 0x70,
0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x42,
0x61, 0x74, 0x63, 0x68, 0x12, 0x36, 0x0a, 0x08, 0x62, 0x63, 0x69, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e,
0x66, 0x6f, 0x52, 0x08, 0x62, 0x63, 0x69, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0d,
0x70, 0x65, 0x65, 0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x07, 0x20,
0x01, 0x28, 0x05, 0x52, 0x0d, 0x70, 0x65, 0x65, 0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64,
0x65, 0x78, 0x22, 0x9a, 0x02, 0x0a, 0x14, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x42, 0x75, 0x66,
0x66, 0x65, 0x72, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x2a, 0x0a, 0x10, 0x72,
0x65, 0x66, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x0f, 0x75, 0x6e, 0x63, 0x6f, 0x6e,
0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
0x52, 0x0f, 0x75, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4d, 0x61, 0x73,
0x6b, 0x12, 0x58, 0x0a, 0x19, 0x74, 0x6f, 0x53, 0x65, 0x6e, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x73, 0x18, 0x03,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x49, 0x6e,
0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63,
0x52, 0x19, 0x74, 0x6f, 0x53, 0x65, 0x6e, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61,
0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x73,
0x68, 0x6f, 0x75, 0x6c, 0x64, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x79, 0x6e, 0x63,
0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x46, 0x6f,
0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x24, 0x0a, 0x0d, 0x70, 0x65, 0x65,
0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05,
0x52, 0x0d, 0x70, 0x65, 0x65, 0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22,
0x89, 0x07, 0x0a, 0x0b, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x12,
0x38, 0x0a, 0x17, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6e,
0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
0x52, 0x17, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6e, 0x64,
0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x11, 0x6f, 0x66, 0x66,
0x65, 0x6e, 0x64, 0x65, 0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02,
0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4a, 0x6f,
0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74,
0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d,
0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x2e, 0x0a,
0x12, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x46, 0x72,
0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x63, 0x61, 0x6e, 0x63, 0x65,
0x6c, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a,
0x12, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x64, 0x46, 0x72,
0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x63, 0x61, 0x6e, 0x63, 0x65,
0x6c, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a,
0x0c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x06, 0x20,
0x01, 0x28, 0x05, 0x52, 0x0c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x73, 0x12, 0x24, 0x0a, 0x0d, 0x68, 0x69, 0x74, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d,
0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x68, 0x69, 0x74, 0x53, 0x74, 0x75,
0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05,
0x52, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x73, 0x12, 0x22, 0x0a, 0x0c, 0x70, 0x75, 0x73, 0x68, 0x62, 0x61, 0x63, 0x6b, 0x56, 0x65, 0x6c,
0x58, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x70, 0x75, 0x73, 0x68, 0x62, 0x61, 0x63,
0x6b, 0x56, 0x65, 0x6c, 0x58, 0x12, 0x22, 0x0a, 0x0c, 0x70, 0x75, 0x73, 0x68, 0x62, 0x61, 0x63,
0x6b, 0x56, 0x65, 0x6c, 0x59, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x70, 0x75, 0x73,
0x68, 0x62, 0x61, 0x63, 0x6b, 0x56, 0x65, 0x6c, 0x59, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x61, 0x6d,
0x61, 0x67, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x64, 0x61, 0x6d, 0x61, 0x67,
0x65, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x65, 0x6c, 0x66, 0x4c, 0x6f, 0x63, 0x6b, 0x56, 0x65, 0x6c,
0x58, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x73, 0x65, 0x6c, 0x66, 0x4c, 0x6f, 0x63,
0x6b, 0x56, 0x65, 0x6c, 0x58, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x65, 0x6c, 0x66, 0x4c, 0x6f, 0x63,
0x6b, 0x56, 0x65, 0x6c, 0x59, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x73, 0x65, 0x6c,
0x66, 0x4c, 0x6f, 0x63, 0x6b, 0x56, 0x65, 0x6c, 0x59, 0x12, 0x24, 0x0a, 0x0d, 0x68, 0x69, 0x74,
0x62, 0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x58, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05,
0x52, 0x0d, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x58, 0x12,
0x24, 0x0a, 0x0d, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x59,
0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x4f, 0x66,
0x66, 0x73, 0x65, 0x74, 0x59, 0x12, 0x20, 0x0a, 0x0b, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x53,
0x69, 0x7a, 0x65, 0x58, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x68, 0x69, 0x74, 0x62,
0x6f, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x58, 0x12, 0x20, 0x0a, 0x0b, 0x68, 0x69, 0x74, 0x62, 0x6f,
0x78, 0x53, 0x69, 0x7a, 0x65, 0x59, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x68, 0x69,
0x74, 0x62, 0x6f, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x59, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x6c, 0x6f,
0x77, 0x55, 0x70, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x62, 0x6c, 0x6f, 0x77, 0x55,
0x70, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28,
0x05, 0x52, 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x62, 0x75, 0x6c,
0x6c, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x05,
0x52, 0x0d, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x12,
0x1c, 0x0a, 0x09, 0x73, 0x70, 0x65, 0x63, 0x69, 0x65, 0x73, 0x49, 0x64, 0x18, 0x15, 0x20, 0x01,
0x28, 0x05, 0x52, 0x09, 0x73, 0x70, 0x65, 0x63, 0x69, 0x65, 0x73, 0x49, 0x64, 0x12, 0x28, 0x0a,
0x0f, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x73, 0x69, 0x6f, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73,
0x18, 0x16, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x73, 0x69, 0x6f,
0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x6c, 0x53, 0x74, 0x61,
0x74, 0x65, 0x18, 0x17, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x62, 0x6c, 0x53, 0x74, 0x61, 0x74,
0x65, 0x12, 0x28, 0x0a, 0x0f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x49, 0x6e, 0x42, 0x6c, 0x53,
0x74, 0x61, 0x74, 0x65, 0x18, 0x18, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x66, 0x72, 0x61, 0x6d,
0x65, 0x73, 0x49, 0x6e, 0x42, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0xc1, 0x08, 0x0a, 0x0e,
0x46, 0x69, 0x72, 0x65, 0x62, 0x61, 0x6c, 0x6c, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x12, 0x38,
0x0a, 0x17, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6e, 0x64,
0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52,
@@ -1730,94 +1874,102 @@ var file_room_downsync_frame_proto_rawDesc = []byte{
0x12, 0x16, 0x0a, 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28, 0x05,
0x52, 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x62, 0x75, 0x6c, 0x6c,
0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x05, 0x52,
0x0d, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x23,
0x0a, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x58, 0x18, 0xe7,
0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72,
0x69, 0x64, 0x58, 0x12, 0x23, 0x0a, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72,
0x69, 0x64, 0x59, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x76, 0x69, 0x72, 0x74,
0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x59, 0x12, 0x13, 0x0a, 0x04, 0x64, 0x69, 0x72, 0x58,
0x18, 0xe9, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x64, 0x69, 0x72, 0x58, 0x12, 0x13, 0x0a,
0x04, 0x64, 0x69, 0x72, 0x59, 0x18, 0xea, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x64, 0x69,
0x72, 0x59, 0x12, 0x13, 0x0a, 0x04, 0x76, 0x65, 0x6c, 0x58, 0x18, 0xeb, 0x07, 0x20, 0x01, 0x28,
0x05, 0x52, 0x04, 0x76, 0x65, 0x6c, 0x58, 0x12, 0x13, 0x0a, 0x04, 0x76, 0x65, 0x6c, 0x59, 0x18,
0xec, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x76, 0x65, 0x6c, 0x59, 0x12, 0x15, 0x0a, 0x05,
0x73, 0x70, 0x65, 0x65, 0x64, 0x18, 0xed, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x70,
0x65, 0x65, 0x64, 0x22, 0xc9, 0x05, 0x0a, 0x12, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f,
0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74,
0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73,
0x74, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x65,
0x72, 0x76, 0x61, 0x6c, 0x54, 0x6f, 0x50, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05,
0x52, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x54, 0x6f, 0x50, 0x69, 0x6e, 0x67,
0x12, 0x34, 0x0a, 0x15, 0x77, 0x69, 0x6c, 0x6c, 0x4b, 0x69, 0x63, 0x6b, 0x49, 0x66, 0x49, 0x6e,
0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
0x15, 0x77, 0x69, 0x6c, 0x6c, 0x4b, 0x69, 0x63, 0x6b, 0x49, 0x66, 0x49, 0x6e, 0x61, 0x63, 0x74,
0x69, 0x76, 0x65, 0x46, 0x6f, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52,
0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x62, 0x6f, 0x75,
0x6e, 0x64, 0x52, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x13, 0x62, 0x61, 0x74, 0x74,
0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18,
0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x75, 0x72,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12, 0x46, 0x0a, 0x1e, 0x69, 0x6e,
0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x65,
0x6c, 0x61, 0x79, 0x54, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01,
0x28, 0x05, 0x52, 0x1e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70,
0x73, 0x79, 0x6e, 0x63, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x54, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e,
0x63, 0x65, 0x12, 0x48, 0x0a, 0x1f, 0x6d, 0x61, 0x78, 0x43, 0x68, 0x61, 0x73, 0x69, 0x6e, 0x67,
0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x50, 0x65, 0x72, 0x55,
0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1f, 0x6d, 0x61, 0x78,
0x43, 0x68, 0x61, 0x73, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61,
0x6d, 0x65, 0x73, 0x50, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x3c, 0x0a, 0x19,
0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65,
0x64, 0x44, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x01, 0x52,
0x19, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74,
0x65, 0x64, 0x44, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x12, 0x3a, 0x0a, 0x18, 0x72, 0x6f,
0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44,
0x74, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x72, 0x6f,
0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44,
0x74, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72,
0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52,
0x0f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x69, 0x7a, 0x65,
0x12, 0x22, 0x0a, 0x0c, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x58,
0x18, 0x0b, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x66, 0x66,
0x73, 0x65, 0x74, 0x58, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x66, 0x66,
0x73, 0x65, 0x74, 0x59, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x73, 0x70, 0x61, 0x63,
0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x59, 0x12, 0x2a, 0x0a, 0x10, 0x63, 0x6f, 0x6c, 0x6c,
0x69, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x53, 0x74, 0x65, 0x70, 0x18, 0x0d, 0x20, 0x01,
0x28, 0x05, 0x52, 0x10, 0x63, 0x6f, 0x6c, 0x6c, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x6e,
0x53, 0x74, 0x65, 0x70, 0x12, 0x39, 0x0a, 0x17, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x61, 0x74,
0x61, 0x4c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18,
0x80, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x61, 0x74,
0x61, 0x4c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22,
0xc2, 0x03, 0x0a, 0x11, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x36, 0x0a, 0x0a, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73,
0x41, 0x72, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x73, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e,
0x63, 0x52, 0x0a, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x41, 0x72, 0x72, 0x12, 0x26, 0x0a,
0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18,
0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e,
0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12, 0x37, 0x0a, 0x0c, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75,
0x6c, 0x6c, 0x65, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74,
0x52, 0x0c, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x73, 0x12, 0x40,
0x0a, 0x0f, 0x66, 0x69, 0x72, 0x65, 0x62, 0x61, 0x6c, 0x6c, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74,
0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
0x2e, 0x46, 0x69, 0x72, 0x65, 0x62, 0x61, 0x6c, 0x6c, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x52,
0x0f, 0x66, 0x69, 0x72, 0x65, 0x62, 0x61, 0x6c, 0x6c, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x73,
0x12, 0x37, 0x0a, 0x16, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x55, 0x6e, 0x63, 0x6f, 0x6e,
0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x18, 0x80, 0x08, 0x20, 0x01, 0x28,
0x04, 0x52, 0x16, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x55, 0x6e, 0x63, 0x6f, 0x6e, 0x66,
0x69, 0x72, 0x6d, 0x65, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x12, 0x2d, 0x0a, 0x11, 0x73, 0x68, 0x6f,
0x75, 0x6c, 0x64, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x79, 0x6e, 0x63, 0x18, 0x81,
0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x46, 0x6f, 0x72,
0x63, 0x65, 0x52, 0x65, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x25, 0x0a, 0x0d, 0x73, 0x70, 0x65, 0x63,
0x69, 0x65, 0x73, 0x49, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x82, 0x08, 0x20, 0x03, 0x28, 0x05,
0x52, 0x0d, 0x73, 0x70, 0x65, 0x63, 0x69, 0x65, 0x73, 0x49, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x12,
0x33, 0x0a, 0x14, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64,
0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x83, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14,
0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x43, 0x6f, 0x75,
0x6e, 0x74, 0x65, 0x72, 0x42, 0x13, 0x5a, 0x11, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x5f, 0x73,
0x72, 0x76, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
0x0d, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x1c,
0x0a, 0x09, 0x73, 0x70, 0x65, 0x63, 0x69, 0x65, 0x73, 0x49, 0x64, 0x18, 0x15, 0x20, 0x01, 0x28,
0x05, 0x52, 0x09, 0x73, 0x70, 0x65, 0x63, 0x69, 0x65, 0x73, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x0f,
0x65, 0x78, 0x70, 0x6c, 0x6f, 0x73, 0x69, 0x6f, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18,
0x16, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x73, 0x69, 0x6f, 0x6e,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x6c, 0x53, 0x74, 0x61, 0x74,
0x65, 0x18, 0x17, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x62, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65,
0x12, 0x28, 0x0a, 0x0f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x49, 0x6e, 0x42, 0x6c, 0x53, 0x74,
0x61, 0x74, 0x65, 0x18, 0x18, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x66, 0x72, 0x61, 0x6d, 0x65,
0x73, 0x49, 0x6e, 0x42, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x76, 0x69,
0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x58, 0x18, 0xe7, 0x07, 0x20, 0x01, 0x28,
0x05, 0x52, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x58, 0x12,
0x23, 0x0a, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x59, 0x18,
0xe8, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47,
0x72, 0x69, 0x64, 0x59, 0x12, 0x13, 0x0a, 0x04, 0x64, 0x69, 0x72, 0x58, 0x18, 0xe9, 0x07, 0x20,
0x01, 0x28, 0x05, 0x52, 0x04, 0x64, 0x69, 0x72, 0x58, 0x12, 0x13, 0x0a, 0x04, 0x64, 0x69, 0x72,
0x59, 0x18, 0xea, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x64, 0x69, 0x72, 0x59, 0x12, 0x13,
0x0a, 0x04, 0x76, 0x65, 0x6c, 0x58, 0x18, 0xeb, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x76,
0x65, 0x6c, 0x58, 0x12, 0x13, 0x0a, 0x04, 0x76, 0x65, 0x6c, 0x59, 0x18, 0xec, 0x07, 0x20, 0x01,
0x28, 0x05, 0x52, 0x04, 0x76, 0x65, 0x6c, 0x59, 0x12, 0x15, 0x0a, 0x05, 0x73, 0x70, 0x65, 0x65,
0x64, 0x18, 0xed, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x70, 0x65, 0x65, 0x64, 0x22,
0xc9, 0x05, 0x0a, 0x12, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64,
0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x67, 0x65, 0x4e,
0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x67, 0x65,
0x4e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c,
0x54, 0x6f, 0x50, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x54, 0x6f, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x15,
0x77, 0x69, 0x6c, 0x6c, 0x4b, 0x69, 0x63, 0x6b, 0x49, 0x66, 0x49, 0x6e, 0x61, 0x63, 0x74, 0x69,
0x76, 0x65, 0x46, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x77, 0x69, 0x6c,
0x6c, 0x4b, 0x69, 0x63, 0x6b, 0x49, 0x66, 0x49, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46,
0x6f, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x6f, 0x6f, 0x6d, 0x49,
0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x6f,
0x6f, 0x6d, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x13, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x75,
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28,
0x03, 0x52, 0x13, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12, 0x46, 0x0a, 0x1e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46,
0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x54,
0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1e,
0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63,
0x44, 0x65, 0x6c, 0x61, 0x79, 0x54, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x48,
0x0a, 0x1f, 0x6d, 0x61, 0x78, 0x43, 0x68, 0x61, 0x73, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x6e, 0x64,
0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x50, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74,
0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1f, 0x6d, 0x61, 0x78, 0x43, 0x68, 0x61, 0x73,
0x69, 0x6e, 0x67, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x50,
0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x3c, 0x0a, 0x19, 0x72, 0x6f, 0x6c, 0x6c,
0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4d,
0x69, 0x6c, 0x6c, 0x69, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x01, 0x52, 0x19, 0x72, 0x6f, 0x6c,
0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74,
0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x12, 0x3a, 0x0a, 0x18, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61,
0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4e, 0x61, 0x6e,
0x6f, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61,
0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4e, 0x61, 0x6e,
0x6f, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x61, 0x63, 0x68,
0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x72, 0x65, 0x6e,
0x64, 0x65, 0x72, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x22, 0x0a, 0x0c,
0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x58, 0x18, 0x0b, 0x20, 0x01,
0x28, 0x01, 0x52, 0x0c, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x58,
0x12, 0x22, 0x0a, 0x0c, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x59,
0x18, 0x0c, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x66, 0x66,
0x73, 0x65, 0x74, 0x59, 0x12, 0x2a, 0x0a, 0x10, 0x63, 0x6f, 0x6c, 0x6c, 0x69, 0x73, 0x69, 0x6f,
0x6e, 0x4d, 0x69, 0x6e, 0x53, 0x74, 0x65, 0x70, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10,
0x63, 0x6f, 0x6c, 0x6c, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x53, 0x74, 0x65, 0x70,
0x12, 0x39, 0x0a, 0x17, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x61, 0x74, 0x61, 0x4c, 0x6f, 0x67,
0x67, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x80, 0x08, 0x20, 0x01,
0x28, 0x08, 0x52, 0x17, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x61, 0x74, 0x61, 0x4c, 0x6f, 0x67,
0x67, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0xc2, 0x03, 0x0a, 0x11,
0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d,
0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69,
0x64, 0x12, 0x36, 0x0a, 0x0a, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x41, 0x72, 0x72, 0x18,
0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x50,
0x6c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x0a, 0x70,
0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x41, 0x72, 0x72, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x6f, 0x75,
0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
0x03, 0x52, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f,
0x73, 0x12, 0x37, 0x0a, 0x0c, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74,
0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
0x2e, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x0c, 0x6d, 0x65,
0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x73, 0x12, 0x40, 0x0a, 0x0f, 0x66, 0x69,
0x72, 0x65, 0x62, 0x61, 0x6c, 0x6c, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x73, 0x18, 0x05, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x46, 0x69, 0x72,
0x65, 0x62, 0x61, 0x6c, 0x6c, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x0f, 0x66, 0x69, 0x72,
0x65, 0x62, 0x61, 0x6c, 0x6c, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x73, 0x12, 0x37, 0x0a, 0x16,
0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x55, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d,
0x65, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x18, 0x80, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x62,
0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x55, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65,
0x64, 0x4d, 0x61, 0x73, 0x6b, 0x12, 0x2d, 0x0a, 0x11, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x46,
0x6f, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x79, 0x6e, 0x63, 0x18, 0x81, 0x08, 0x20, 0x01, 0x28,
0x08, 0x52, 0x11, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x52, 0x65,
0x73, 0x79, 0x6e, 0x63, 0x12, 0x25, 0x0a, 0x0d, 0x73, 0x70, 0x65, 0x63, 0x69, 0x65, 0x73, 0x49,
0x64, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x82, 0x08, 0x20, 0x03, 0x28, 0x05, 0x52, 0x0d, 0x73, 0x70,
0x65, 0x63, 0x69, 0x65, 0x73, 0x49, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x14, 0x62,
0x75, 0x6c, 0x6c, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x43, 0x6f, 0x75, 0x6e,
0x74, 0x65, 0x72, 0x18, 0x83, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x62, 0x75, 0x6c, 0x6c,
0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
0x42, 0x13, 0x5a, 0x11, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x5f, 0x73, 0x72, 0x76, 0x2f, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

@@ -46,6 +46,7 @@ func Serve(c *gin.Context) {
c.AbortWithStatus(http.StatusBadRequest)
return
}
boundRoomId := 0
expectedRoomId := 0
var err error
@@ -395,3 +396,89 @@ func Serve(c *gin.Context) {
startOrFeedHeartbeatWatchdog(conn)
go receivingLoopAgainstPlayer()
}
func HandleSecondaryWsSessionForPlayer(c *gin.Context) {
token, ok := c.GetQuery("intAuthToken")
if !ok {
Logger.Warn("Secondary ws session req must have intAuthToken param!")
c.AbortWithStatus(http.StatusBadRequest)
return
}
boundRoomId := 0
var err error = nil
if boundRoomIdStr, hasBoundRoomId := c.GetQuery("boundRoomId"); hasBoundRoomId {
boundRoomId, err = strconv.Atoi(boundRoomIdStr)
if err != nil {
c.AbortWithStatus(http.StatusBadRequest)
return
}
} else {
Logger.Warn("Secondary ws session req must have boundRoomId param:", zap.Any("intAuthToken", token))
c.AbortWithStatus(http.StatusBadRequest)
return
}
var pRoom *models.Room = nil
// Deliberately querying playerId after querying room, because the former is against persistent storage and could be slow!
if tmpPRoom, existent := (*models.RoomMapManagerIns)[int32(boundRoomId)]; !existent {
Logger.Warn("Secondary ws session failed to get:\n", zap.Any("intAuthToken", token), zap.Any("forBoundRoomId", boundRoomId))
c.AbortWithStatus(http.StatusBadRequest)
} else {
pRoom = tmpPRoom
}
// TODO: Wrap the following 2 stmts by sql transaction!
playerId, err := models.GetPlayerIdByToken(token)
if err != nil || playerId == 0 {
// TODO: Abort with specific message.
Logger.Warn("Secondary ws session playerLogin record not found for ws authentication:", zap.Any("intAuthToken", token))
c.AbortWithStatus(http.StatusBadRequest)
return
}
Logger.Info("Secondary ws session playerLogin record has been found for ws authentication:", zap.Any("playerId", playerId), zap.Any("intAuthToken", token), zap.Any("boundRoomId", boundRoomId))
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
Logger.Error("Secondary ws session upgrade:", zap.Error(err), zap.Any("playerId", playerId))
c.AbortWithStatus(http.StatusBadRequest)
return
}
connHasBeenSignaledToClose := int32(0)
pConnHasBeenSignaledToClose := &connHasBeenSignaledToClose
signalToCloseConnOfThisPlayer := func(customRetCode int, customRetMsg string) {
if swapped := atomic.CompareAndSwapInt32(pConnHasBeenSignaledToClose, 0, 1); !swapped {
return
}
Logger.Warn("Secondary ws session signalToCloseConnOfThisPlayer:", zap.Any("playerId", playerId), zap.Any("customRetCode", customRetCode), zap.Any("customRetMsg", customRetMsg))
defer func() {
if r := recover(); r != nil {
Logger.Error("Secondary ws session recovered from: ", zap.Any("panic", r))
}
}()
closeMessage := websocket.FormatCloseMessage(customRetCode, customRetMsg)
err := conn.WriteControl(websocket.CloseMessage, closeMessage, time.Now().Add(time.Millisecond*(ConstVals.Ws.WillKickIfInactiveFor)))
if err != nil {
Logger.Error("Secondary ws session unable to send the CloseFrame control message to player(client-side):", zap.Any("playerId", playerId), zap.Error(err))
}
time.AfterFunc(3*time.Second, func() {
// To actually terminates the underlying TCP connection which might be in `CLOSE_WAIT` state if inspected by `netstat`.
conn.Close()
})
}
onReceivedCloseMessageFromClient := func(code int, text string) error {
Logger.Warn("Secondary ws session triggered `onReceivedCloseMessageFromClient`:", zap.Any("code", code), zap.Any("playerId", playerId), zap.Any("message", text))
signalToCloseConnOfThisPlayer(code, text)
return nil
}
conn.SetCloseHandler(onReceivedCloseMessageFromClient)
pRoom.SetSecondarySession(int32(playerId), conn, signalToCloseConnOfThisPlayer)
}

File diff suppressed because one or more lines are too long

BIN
charts/ServerClients.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

BIN
charts/UDPEssentials.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 MiB

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
{
"ver": "1.0.5",
"uuid": "d41313ca-b2c3-4436-a05f-7e0eb290b1e6",
"uuid": "40edd08e-316c-44b8-a50f-bd173554c554",
"isPlugin": true,
"loadPluginInWeb": true,
"loadPluginInNative": true,

View File

@@ -0,0 +1,7 @@
{
"ver": "1.0.1",
"uuid": "c7c2ac6e-f1ea-4233-b6a4-aa5b96b61e17",
"isSubpackage": false,
"subpackageName": "",
"subMetas": {}
}

View File

@@ -0,0 +1,55 @@
{
"__type__": "cc.AnimationClip",
"_name": "Fireball1Explosion",
"_objFlags": 0,
"_native": "",
"_duration": 0.26666666666666666,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "f4ad4f9f-4890-450b-9334-68fe6b903893"
}
},
{
"frame": 0.05,
"value": {
"__uuid__": "c6a5994f-251d-4191-a550-dfef979bab59"
}
},
{
"frame": 0.11666666666666667,
"value": {
"__uuid__": "417e58d9-e364-47f7-9364-f31ad3452adc"
}
},
{
"frame": 0.15,
"value": {
"__uuid__": "8b566f26-b34d-4da6-bdaa-078358a5b685"
}
},
{
"frame": 0.2,
"value": {
"__uuid__": "6ec5f75d-307e-4292-b667-cbbb5a52c2f6"
}
},
{
"frame": 0.25,
"value": {
"__uuid__": "d89977f1-d927-4a08-9591-9feb1daf68c8"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,5 @@
{
"ver": "2.1.0",
"uuid": "7941215a-2b8c-4798-954b-4f1b16d5f6f5",
"subMetas": {}
}

View File

@@ -0,0 +1,79 @@
{
"__type__": "cc.AnimationClip",
"_name": "MeleeExplosion1",
"_objFlags": 0,
"_native": "",
"_duration": 0.16666666666666666,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "ab4866e8-ce52-4bc1-be19-b03687acf0d6"
}
},
{
"frame": 0.016666666666666666,
"value": {
"__uuid__": "67cc8a51-0ebe-49db-a941-7aabc5655ecf"
}
},
{
"frame": 0.03333333333333333,
"value": {
"__uuid__": "367592d0-3566-4b6a-8707-01d6a8dbe34a"
}
},
{
"frame": 0.05,
"value": {
"__uuid__": "cc336b1e-b5d8-4a89-96fc-7ada0e232389"
}
},
{
"frame": 0.06666666666666667,
"value": {
"__uuid__": "a457cc63-08bd-4cfa-b84a-7287d0343ecf"
}
},
{
"frame": 0.08333333333333333,
"value": {
"__uuid__": "89697d35-cde3-4392-a231-db91d4ede29b"
}
},
{
"frame": 0.1,
"value": {
"__uuid__": "3815bf7a-0a48-40e0-b791-0a0be9ec0da6"
}
},
{
"frame": 0.11666666666666667,
"value": {
"__uuid__": "20e691ee-a0c0-4710-8981-8dee1911e819"
}
},
{
"frame": 0.13333333333333333,
"value": {
"__uuid__": "94e678c5-0780-4f2b-bf3b-86c6c0a75c23"
}
},
{
"frame": 0.15,
"value": {
"__uuid__": "af4f9c62-4c7e-43a4-b9b3-dd3effbbbafb"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,5 @@
{
"ver": "2.1.0",
"uuid": "954a2924-89df-4df4-93fc-36d2b22e7619",
"subMetas": {}
}

View File

@@ -0,0 +1,79 @@
{
"__type__": "cc.AnimationClip",
"_name": "MeleeExplosion2",
"_objFlags": 0,
"_native": "",
"_duration": 0.26666666666666666,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "89e54317-7835-4d4c-9c04-579da8b33c54"
}
},
{
"frame": 0.016666666666666666,
"value": {
"__uuid__": "2a186e00-a0c5-4c8a-b0ab-c84d56dcee7c"
}
},
{
"frame": 0.05,
"value": {
"__uuid__": "083168e3-6ccc-4c5b-a800-2554bffc67d4"
}
},
{
"frame": 0.08333333333333333,
"value": {
"__uuid__": "d4b12ec9-6f04-493c-91e5-22b1a212262a"
}
},
{
"frame": 0.13333333333333333,
"value": {
"__uuid__": "13038788-b0f9-4714-960b-c98619a0d0ce"
}
},
{
"frame": 0.16666666666666666,
"value": {
"__uuid__": "94c21ed7-94a2-47a4-9537-fe5d9c51d7b0"
}
},
{
"frame": 0.2,
"value": {
"__uuid__": "d5340298-923c-4bd7-9fd7-7a2e029a2b44"
}
},
{
"frame": 0.21666666666666667,
"value": {
"__uuid__": "c4b145c0-0145-4e09-8559-9ef508d95be8"
}
},
{
"frame": 0.23333333333333334,
"value": {
"__uuid__": "79398d4d-305e-4987-b199-d9d9649cf490"
}
},
{
"frame": 0.25,
"value": {
"__uuid__": "c032eb65-fdf3-41e6-b868-d95df34168df"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,5 @@
{
"ver": "2.1.0",
"uuid": "5bd304eb-c8ba-426f-a9ab-5698ac62de85",
"subMetas": {}
}

View File

@@ -0,0 +1,79 @@
{
"__type__": "cc.AnimationClip",
"_name": "MeleeExplosion3",
"_objFlags": 0,
"_native": "",
"_duration": 0.26666666666666666,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "20d9ce6b-d9ab-4402-8c59-770ad0adf570"
}
},
{
"frame": 0.016666666666666666,
"value": {
"__uuid__": "0654601f-6788-4a2c-aed4-8dfbe1c5fdd0"
}
},
{
"frame": 0.03333333333333333,
"value": {
"__uuid__": "0913e11a-c796-4b58-94cf-f70b3869deff"
}
},
{
"frame": 0.06666666666666667,
"value": {
"__uuid__": "d6b58622-2cc3-4ee6-a34f-1a18deb73700"
}
},
{
"frame": 0.08333333333333333,
"value": {
"__uuid__": "b83c6261-b86f-4323-ad11-7375cac02a2b"
}
},
{
"frame": 0.11666666666666667,
"value": {
"__uuid__": "b458c047-b7b5-4476-996e-d4c1ca85ef9c"
}
},
{
"frame": 0.15,
"value": {
"__uuid__": "3971256a-8120-448e-8adf-de8d67dedfd3"
}
},
{
"frame": 0.18333333333333332,
"value": {
"__uuid__": "0e548d92-36c8-4795-b3dc-2bc2cfcd7170"
}
},
{
"frame": 0.21666666666666667,
"value": {
"__uuid__": "25f94245-87b0-4954-abab-c817c80fed37"
}
},
{
"frame": 0.25,
"value": {
"__uuid__": "20d9ce6b-d9ab-4402-8c59-770ad0adf570"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,5 @@
{
"ver": "2.1.0",
"uuid": "5054633c-a588-4506-b4ac-eef29b1d8511",
"subMetas": {}
}

View File

@@ -0,0 +1,476 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>frames</key>
<dict>
<key>Explosion1_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{71,67}</string>
<key>spriteSourceSize</key>
<string>{71,67}</string>
<key>textureRect</key>
<string>{{0,506},{71,67}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion1_10.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{71,67}</string>
<key>spriteSourceSize</key>
<string>{71,67}</string>
<key>textureRect</key>
<string>{{0,577},{71,67}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion1_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{71,67}</string>
<key>spriteSourceSize</key>
<string>{71,67}</string>
<key>textureRect</key>
<string>{{67,506},{71,67}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion1_3.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{71,67}</string>
<key>spriteSourceSize</key>
<string>{71,67}</string>
<key>textureRect</key>
<string>{{67,577},{71,67}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion1_4.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{71,67}</string>
<key>spriteSourceSize</key>
<string>{71,67}</string>
<key>textureRect</key>
<string>{{134,506},{71,67}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion1_5.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{71,67}</string>
<key>spriteSourceSize</key>
<string>{71,67}</string>
<key>textureRect</key>
<string>{{134,577},{71,67}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion1_6.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{71,67}</string>
<key>spriteSourceSize</key>
<string>{71,67}</string>
<key>textureRect</key>
<string>{{355,503},{71,67}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion1_7.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{71,67}</string>
<key>spriteSourceSize</key>
<string>{71,67}</string>
<key>textureRect</key>
<string>{{426,503},{71,67}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion1_8.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{71,67}</string>
<key>spriteSourceSize</key>
<string>{71,67}</string>
<key>textureRect</key>
<string>{{355,570},{71,67}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion1_9.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{71,67}</string>
<key>spriteSourceSize</key>
<string>{71,67}</string>
<key>textureRect</key>
<string>{{422,570},{71,67}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion2_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{88,45}</string>
<key>spriteSourceSize</key>
<string>{88,45}</string>
<key>textureRect</key>
<string>{{462,0},{88,45}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion2_10.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{88,45}</string>
<key>spriteSourceSize</key>
<string>{88,45}</string>
<key>textureRect</key>
<string>{{462,88},{88,45}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion2_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{88,45}</string>
<key>spriteSourceSize</key>
<string>{88,45}</string>
<key>textureRect</key>
<string>{{462,176},{88,45}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion2_3.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{88,45}</string>
<key>spriteSourceSize</key>
<string>{88,45}</string>
<key>textureRect</key>
<string>{{462,264},{88,45}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion2_4.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{88,45}</string>
<key>spriteSourceSize</key>
<string>{88,45}</string>
<key>textureRect</key>
<string>{{0,304},{88,45}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion2_5.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{88,45}</string>
<key>spriteSourceSize</key>
<string>{88,45}</string>
<key>textureRect</key>
<string>{{88,304},{88,45}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion2_6.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{88,45}</string>
<key>spriteSourceSize</key>
<string>{88,45}</string>
<key>textureRect</key>
<string>{{176,304},{88,45}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion2_7.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{88,45}</string>
<key>spriteSourceSize</key>
<string>{88,45}</string>
<key>textureRect</key>
<string>{{264,304},{88,45}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion2_8.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{88,45}</string>
<key>spriteSourceSize</key>
<string>{88,45}</string>
<key>textureRect</key>
<string>{{352,304},{88,45}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion2_9.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{88,45}</string>
<key>spriteSourceSize</key>
<string>{88,45}</string>
<key>textureRect</key>
<string>{{456,352},{88,45}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion3_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{154,152}</string>
<key>spriteSourceSize</key>
<string>{154,152}</string>
<key>textureRect</key>
<string>{{0,0},{154,152}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion3_10.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{154,152}</string>
<key>spriteSourceSize</key>
<string>{154,152}</string>
<key>textureRect</key>
<string>{{154,0},{154,152}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion3_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{154,152}</string>
<key>spriteSourceSize</key>
<string>{154,152}</string>
<key>textureRect</key>
<string>{{308,0},{154,152}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion3_3.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{154,152}</string>
<key>spriteSourceSize</key>
<string>{154,152}</string>
<key>textureRect</key>
<string>{{0,152},{154,152}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion3_4.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{154,152}</string>
<key>spriteSourceSize</key>
<string>{154,152}</string>
<key>textureRect</key>
<string>{{154,152},{154,152}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion3_5.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{154,152}</string>
<key>spriteSourceSize</key>
<string>{154,152}</string>
<key>textureRect</key>
<string>{{308,152},{154,152}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion3_6.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{154,152}</string>
<key>spriteSourceSize</key>
<string>{154,152}</string>
<key>textureRect</key>
<string>{{0,352},{154,152}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion3_7.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{154,152}</string>
<key>spriteSourceSize</key>
<string>{154,152}</string>
<key>textureRect</key>
<string>{{152,349},{154,152}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion3_8.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{154,152}</string>
<key>spriteSourceSize</key>
<string>{154,152}</string>
<key>textureRect</key>
<string>{{201,503},{154,152}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion3_9.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{154,152}</string>
<key>spriteSourceSize</key>
<string>{154,152}</string>
<key>textureRect</key>
<string>{{304,349},{154,152}}</string>
<key>textureRotated</key>
<true/>
</dict>
</dict>
<key>metadata</key>
<dict>
<key>format</key>
<integer>3</integer>
<key>pixelFormat</key>
<string>RGBA8888</string>
<key>premultiplyAlpha</key>
<false/>
<key>realTextureFileName</key>
<string>MeleeExplosions.png</string>
<key>size</key>
<string>{507,655}</string>
<key>smartupdate</key>
<string>$TexturePacker:SmartUpdate:6c1498ee6f30bdad4abeb6a9f6af8367:4c81e1a1720f2ad3535ac93f1b42991f:d9b184ec81b83b14db5cf31d298727df$</string>
<key>textureFileName</key>
<string>MeleeExplosions.png</string>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,672 @@
{
"ver": "1.2.4",
"uuid": "1c4c1dcb-54af-485b-9119-abd6d6d84526",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"size": {
"width": 507,
"height": 655
},
"type": "Texture Packer",
"subMetas": {
"Explosion1_1.png": {
"ver": "1.0.4",
"uuid": "ab4866e8-ce52-4bc1-be19-b03687acf0d6",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 506,
"width": 71,
"height": 67,
"rawWidth": 71,
"rawHeight": 67,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion1_10.png": {
"ver": "1.0.4",
"uuid": "af4f9c62-4c7e-43a4-b9b3-dd3effbbbafb",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 577,
"width": 71,
"height": 67,
"rawWidth": 71,
"rawHeight": 67,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion1_2.png": {
"ver": "1.0.4",
"uuid": "67cc8a51-0ebe-49db-a941-7aabc5655ecf",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 67,
"trimY": 506,
"width": 71,
"height": 67,
"rawWidth": 71,
"rawHeight": 67,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion1_3.png": {
"ver": "1.0.4",
"uuid": "367592d0-3566-4b6a-8707-01d6a8dbe34a",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 67,
"trimY": 577,
"width": 71,
"height": 67,
"rawWidth": 71,
"rawHeight": 67,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion1_4.png": {
"ver": "1.0.4",
"uuid": "cc336b1e-b5d8-4a89-96fc-7ada0e232389",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 134,
"trimY": 506,
"width": 71,
"height": 67,
"rawWidth": 71,
"rawHeight": 67,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion1_5.png": {
"ver": "1.0.4",
"uuid": "a457cc63-08bd-4cfa-b84a-7287d0343ecf",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 134,
"trimY": 577,
"width": 71,
"height": 67,
"rawWidth": 71,
"rawHeight": 67,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion1_6.png": {
"ver": "1.0.4",
"uuid": "89697d35-cde3-4392-a231-db91d4ede29b",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 355,
"trimY": 503,
"width": 71,
"height": 67,
"rawWidth": 71,
"rawHeight": 67,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion1_7.png": {
"ver": "1.0.4",
"uuid": "3815bf7a-0a48-40e0-b791-0a0be9ec0da6",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 426,
"trimY": 503,
"width": 71,
"height": 67,
"rawWidth": 71,
"rawHeight": 67,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion1_8.png": {
"ver": "1.0.4",
"uuid": "20e691ee-a0c0-4710-8981-8dee1911e819",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 355,
"trimY": 570,
"width": 71,
"height": 67,
"rawWidth": 71,
"rawHeight": 67,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion1_9.png": {
"ver": "1.0.4",
"uuid": "94e678c5-0780-4f2b-bf3b-86c6c0a75c23",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 422,
"trimY": 570,
"width": 71,
"height": 67,
"rawWidth": 71,
"rawHeight": 67,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion2_1.png": {
"ver": "1.0.4",
"uuid": "89e54317-7835-4d4c-9c04-579da8b33c54",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 462,
"trimY": 0,
"width": 88,
"height": 45,
"rawWidth": 88,
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion2_10.png": {
"ver": "1.0.4",
"uuid": "c032eb65-fdf3-41e6-b868-d95df34168df",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 462,
"trimY": 88,
"width": 88,
"height": 45,
"rawWidth": 88,
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion2_2.png": {
"ver": "1.0.4",
"uuid": "2a186e00-a0c5-4c8a-b0ab-c84d56dcee7c",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 462,
"trimY": 176,
"width": 88,
"height": 45,
"rawWidth": 88,
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion2_3.png": {
"ver": "1.0.4",
"uuid": "083168e3-6ccc-4c5b-a800-2554bffc67d4",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 462,
"trimY": 264,
"width": 88,
"height": 45,
"rawWidth": 88,
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion2_4.png": {
"ver": "1.0.4",
"uuid": "d4b12ec9-6f04-493c-91e5-22b1a212262a",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 304,
"width": 88,
"height": 45,
"rawWidth": 88,
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion2_5.png": {
"ver": "1.0.4",
"uuid": "13038788-b0f9-4714-960b-c98619a0d0ce",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 88,
"trimY": 304,
"width": 88,
"height": 45,
"rawWidth": 88,
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion2_6.png": {
"ver": "1.0.4",
"uuid": "94c21ed7-94a2-47a4-9537-fe5d9c51d7b0",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 176,
"trimY": 304,
"width": 88,
"height": 45,
"rawWidth": 88,
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion2_7.png": {
"ver": "1.0.4",
"uuid": "d5340298-923c-4bd7-9fd7-7a2e029a2b44",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 264,
"trimY": 304,
"width": 88,
"height": 45,
"rawWidth": 88,
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion2_8.png": {
"ver": "1.0.4",
"uuid": "c4b145c0-0145-4e09-8559-9ef508d95be8",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 352,
"trimY": 304,
"width": 88,
"height": 45,
"rawWidth": 88,
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion2_9.png": {
"ver": "1.0.4",
"uuid": "79398d4d-305e-4987-b199-d9d9649cf490",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 456,
"trimY": 352,
"width": 88,
"height": 45,
"rawWidth": 88,
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion3_1.png": {
"ver": "1.0.4",
"uuid": "84e28787-c6cb-435b-8f59-20d9afe6bf3a",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 154,
"height": 152,
"rawWidth": 154,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion3_10.png": {
"ver": "1.0.4",
"uuid": "20d9ce6b-d9ab-4402-8c59-770ad0adf570",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 154,
"trimY": 0,
"width": 154,
"height": 152,
"rawWidth": 154,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion3_2.png": {
"ver": "1.0.4",
"uuid": "0654601f-6788-4a2c-aed4-8dfbe1c5fdd0",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 308,
"trimY": 0,
"width": 154,
"height": 152,
"rawWidth": 154,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion3_3.png": {
"ver": "1.0.4",
"uuid": "0913e11a-c796-4b58-94cf-f70b3869deff",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 152,
"width": 154,
"height": 152,
"rawWidth": 154,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion3_4.png": {
"ver": "1.0.4",
"uuid": "d6b58622-2cc3-4ee6-a34f-1a18deb73700",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 154,
"trimY": 152,
"width": 154,
"height": 152,
"rawWidth": 154,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion3_5.png": {
"ver": "1.0.4",
"uuid": "b83c6261-b86f-4323-ad11-7375cac02a2b",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 308,
"trimY": 152,
"width": 154,
"height": 152,
"rawWidth": 154,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion3_6.png": {
"ver": "1.0.4",
"uuid": "b458c047-b7b5-4476-996e-d4c1ca85ef9c",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 352,
"width": 154,
"height": 152,
"rawWidth": 154,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion3_7.png": {
"ver": "1.0.4",
"uuid": "3971256a-8120-448e-8adf-de8d67dedfd3",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 152,
"trimY": 349,
"width": 154,
"height": 152,
"rawWidth": 154,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion3_8.png": {
"ver": "1.0.4",
"uuid": "0e548d92-36c8-4795-b3dc-2bc2cfcd7170",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 201,
"trimY": 503,
"width": 154,
"height": 152,
"rawWidth": 154,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion3_9.png": {
"ver": "1.0.4",
"uuid": "25f94245-87b0-4954-abab-c817c80fed37",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 304,
"trimY": 349,
"width": 154,
"height": 152,
"rawWidth": 154,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,12 @@
{
"ver": "2.3.3",
"uuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"type": "raw",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"platformSettings": {},
"subMetas": {}
}

View File

@@ -0,0 +1,7 @@
{
"ver": "1.0.1",
"uuid": "b07a911d-2d61-486d-9edc-1b3ba53c9911",
"isSubpackage": false,
"subpackageName": "",
"subMetas": {}
}

View File

@@ -0,0 +1,145 @@
{
"__type__": "cc.AnimationClip",
"_name": "Fireball1",
"_objFlags": 0,
"_native": "",
"_duration": 0.35,
"sample": 60,
"speed": 1,
"wrapMode": 2,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "dbe67025-9878-4e13-8f3d-81e04734810a"
}
},
{
"frame": 0.016666666666666666,
"value": {
"__uuid__": "e92702d5-d5fd-49e6-ab6b-2296b43fa6d6"
}
},
{
"frame": 0.03333333333333333,
"value": {
"__uuid__": "e1a89340-0b92-4e6b-93f2-e983302d70ce"
}
},
{
"frame": 0.05,
"value": {
"__uuid__": "b0bb4a7a-4ae3-48fc-9913-3b6d1d36c56f"
}
},
{
"frame": 0.06666666666666667,
"value": {
"__uuid__": "b44d585b-8e18-4767-b263-ed3a53cd3250"
}
},
{
"frame": 0.08333333333333333,
"value": {
"__uuid__": "a87a9ea8-2d84-4a3b-83e3-a4d7b8ac96b8"
}
},
{
"frame": 0.1,
"value": {
"__uuid__": "a1604f9d-c0ea-4f92-b09b-3608245bda8e"
}
},
{
"frame": 0.11666666666666667,
"value": {
"__uuid__": "4372818f-1e44-4180-a0ce-4a34cee4fc5b"
}
},
{
"frame": 0.13333333333333333,
"value": {
"__uuid__": "dbe67025-9878-4e13-8f3d-81e04734810a"
}
},
{
"frame": 0.15,
"value": {
"__uuid__": "5d867617-7f50-4fa8-804d-ce28c47ea407"
}
},
{
"frame": 0.16666666666666666,
"value": {
"__uuid__": "824c9bee-42b7-4a94-86f8-6356f11aee16"
}
},
{
"frame": 0.18333333333333332,
"value": {
"__uuid__": "6389164e-93bb-4d4d-9740-5e2d5cdb1029"
}
},
{
"frame": 0.2,
"value": {
"__uuid__": "d184a083-6043-4ca6-bd14-8db1b6be1d2e"
}
},
{
"frame": 0.21666666666666667,
"value": {
"__uuid__": "361b1722-e362-46e5-939e-e2d1666df374"
}
},
{
"frame": 0.23333333333333334,
"value": {
"__uuid__": "662fbe4f-a1f4-46f7-83e4-eafd021432da"
}
},
{
"frame": 0.25,
"value": {
"__uuid__": "5e509118-a44b-4e7f-9686-c6bb0b30f0b0"
}
},
{
"frame": 0.26666666666666666,
"value": {
"__uuid__": "bc1110c7-4423-4c43-965c-0cb3dd8e31ff"
}
},
{
"frame": 0.2833333333333333,
"value": {
"__uuid__": "33cc8d11-1568-47a7-b4f1-cef4888302e5"
}
},
{
"frame": 0.3,
"value": {
"__uuid__": "83bb5dd3-510c-4fce-b393-840f14efb8cd"
}
},
{
"frame": 0.31666666666666665,
"value": {
"__uuid__": "1db706f5-366a-421c-843f-a4bb016f80ec"
}
},
{
"frame": 0.3333333333333333,
"value": {
"__uuid__": "41a4f35a-01c0-4a22-b5cc-7bfe25ed4501"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,5 @@
{
"ver": "2.1.0",
"uuid": "ba12416b-eec3-4260-8402-7fc25b125624",
"subMetas": {}
}

View File

@@ -18,61 +18,43 @@
}
},
{
"frame": 0.06666666666666667,
"frame": 0.05,
"value": {
"__uuid__": "dd9a00aa-ddbc-4b01-a7cb-3c43c3a655b6"
}
},
{
"frame": 0.11666666666666667,
"value": {
"__uuid__": "f66e83bd-1afc-4957-bb16-488d70566ed1"
}
},
{
"frame": 0.16666666666666666,
"value": {
"__uuid__": "bd682c41-dc62-49ff-a96a-18b33e50a6de"
}
},
{
"frame": 0.23333333333333334,
"value": {
"__uuid__": "94ccab85-e32f-4e13-b0e5-72c798f78ad1"
}
},
{
"frame": 0.3,
"frame": 0.08333333333333333,
"value": {
"__uuid__": "e80d3a01-5048-42b7-a280-cb6aa01602c2"
}
},
{
"frame": 0.36666666666666664,
"frame": 0.11666666666666667,
"value": {
"__uuid__": "d899088c-be62-47b4-9ebf-0a89a2261565"
}
},
{
"frame": 0.4166666666666667,
"frame": 0.15,
"value": {
"__uuid__": "5b1e5aa7-fd82-47ae-a5b2-6d4983d848ed"
}
},
{
"frame": 0.48333333333333334,
"frame": 0.18333333333333332,
"value": {
"__uuid__": "c2945988-b4bb-4583-a5ef-2fa02b23a347"
}
},
{
"frame": 0.5666666666666667,
"frame": 0.23333333333333334,
"value": {
"__uuid__": "070ea1e3-9c07-4735-8b94-515ef70216ad"
}
},
{
"frame": 0.6666666666666666,
"frame": 0.2833333333333333,
"value": {
"__uuid__": "3b8bc5c0-26df-4218-b7dc-134a36080a35"
}

View File

@@ -0,0 +1,61 @@
{
"__type__": "cc.AnimationClip",
"_name": "Dashing",
"_objFlags": 0,
"_native": "",
"_duration": 0.35,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "cf396dac-50c9-4389-90c0-55f49fd3276d"
}
},
{
"frame": 0.05,
"value": {
"__uuid__": "b9e4b5d5-c296-48c8-aa60-d22db0e5a632"
}
},
{
"frame": 0.11666666666666667,
"value": {
"__uuid__": "e456c710-69f5-4dcc-9f5d-dd486a9198a1"
}
},
{
"frame": 0.16666666666666666,
"value": {
"__uuid__": "ec6df76f-0004-4216-9b83-449487fe0cda"
}
},
{
"frame": 0.23333333333333334,
"value": {
"__uuid__": "26032d0f-845c-4b96-89a6-d88113ed7827"
}
},
{
"frame": 0.2833333333333333,
"value": {
"__uuid__": "e3e0169c-3c56-4206-a20e-35e4d0471873"
}
},
{
"frame": 0.3333333333333333,
"value": {
"__uuid__": "80b98036-c5de-492b-b0e8-f1703f3a7d20"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,5 @@
{
"ver": "2.1.0",
"uuid": "38b2c892-347b-4009-93f8-65b2ab1614f0",
"subMetas": {}
}

View File

@@ -15,9 +15,9 @@
<key>spriteSourceSize</key>
<string>{112,128}</string>
<key>textureRect</key>
<string>{{824,544},{112,128}}</string>
<string>{{384,989},{112,128}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>Atk1_1.png</key>
<dict>
@@ -30,9 +30,9 @@
<key>spriteSourceSize</key>
<string>{112,128}</string>
<key>textureRect</key>
<string>{{0,1200},{112,128}}</string>
<string>{{256,990},{112,128}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>Atk1_10.png</key>
<dict>
@@ -90,9 +90,9 @@
<key>spriteSourceSize</key>
<string>{112,128}</string>
<key>textureRect</key>
<string>{{0,964},{112,128}}</string>
<string>{{128,1082},{112,128}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>Atk1_4.png</key>
<dict>
@@ -105,9 +105,9 @@
<key>spriteSourceSize</key>
<string>{112,128}</string>
<key>textureRect</key>
<string>{{112,964},{112,128}}</string>
<string>{{0,1188},{112,128}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>Atk1_5.png</key>
<dict>
@@ -120,7 +120,7 @@
<key>spriteSourceSize</key>
<string>{96,128}</string>
<key>textureRect</key>
<string>{{840,288},{96,128}}</string>
<string>{{512,643},{96,128}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -135,7 +135,7 @@
<key>spriteSourceSize</key>
<string>{96,128}</string>
<key>textureRect</key>
<string>{{840,416},{96,128}}</string>
<string>{{512,771},{96,128}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -165,7 +165,7 @@
<key>spriteSourceSize</key>
<string>{80,128}</string>
<key>textureRect</key>
<string>{{936,384},{80,128}}</string>
<string>{{937,384},{80,128}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -180,7 +180,7 @@
<key>spriteSourceSize</key>
<string>{80,128}</string>
<key>textureRect</key>
<string>{{936,512},{80,128}}</string>
<string>{{528,515},{80,128}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -195,7 +195,7 @@
<key>spriteSourceSize</key>
<string>{80,128}</string>
<key>textureRect</key>
<string>{{936,640},{80,128}}</string>
<string>{{936,512},{80,128}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -210,7 +210,7 @@
<key>spriteSourceSize</key>
<string>{96,128}</string>
<key>textureRect</key>
<string>{{582,531},{96,128}}</string>
<string>{{512,899},{96,128}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -225,7 +225,7 @@
<key>spriteSourceSize</key>
<string>{128,112}</string>
<key>textureRect</key>
<string>{{326,871},{128,112}}</string>
<string>{{0,1076},{128,112}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -240,7 +240,7 @@
<key>spriteSourceSize</key>
<string>{96,96}</string>
<key>textureRect</key>
<string>{{696,1200},{96,96}}</string>
<string>{{688,1357},{96,96}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -255,7 +255,7 @@
<key>spriteSourceSize</key>
<string>{96,112}</string>
<key>textureRect</key>
<string>{{416,983},{96,112}}</string>
<string>{{240,1360},{96,112}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -270,7 +270,7 @@
<key>spriteSourceSize</key>
<string>{96,112}</string>
<key>textureRect</key>
<string>{{656,1092},{96,112}}</string>
<string>{{352,1358},{96,112}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -285,9 +285,9 @@
<key>spriteSourceSize</key>
<string>{96,112}</string>
<key>textureRect</key>
<string>{{528,1113},{96,112}}</string>
<string>{{920,1072},{96,112}}</string>
<key>textureRotated</key>
<true/>
<false/>
</dict>
<key>Atk2_5.png</key>
<dict>
@@ -300,9 +300,9 @@
<key>spriteSourceSize</key>
<string>{96,112}</string>
<key>textureRect</key>
<string>{{392,1207},{96,112}}</string>
<string>{{914,1184},{96,112}}</string>
<key>textureRotated</key>
<true/>
<false/>
</dict>
<key>Atk2_6.png</key>
<dict>
@@ -330,7 +330,7 @@
<key>spriteSourceSize</key>
<string>{128,112}</string>
<key>textureRect</key>
<string>{{454,871},{128,112}}</string>
<string>{{806,631},{128,112}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -525,7 +525,7 @@
<key>spriteSourceSize</key>
<string>{96,128}</string>
<key>textureRect</key>
<string>{{582,659},{96,128}}</string>
<string>{{512,1027},{96,128}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -540,7 +540,7 @@
<key>spriteSourceSize</key>
<string>{112,112}</string>
<key>textureRect</key>
<string>{{240,1081},{112,112}}</string>
<string>{{802,1149},{112,112}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -555,9 +555,9 @@
<key>spriteSourceSize</key>
<string>{96,112}</string>
<key>textureRect</key>
<string>{{504,1209},{96,112}}</string>
<string>{{800,1261},{96,112}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>Atked1_3.png</key>
<dict>
@@ -570,7 +570,7 @@
<key>spriteSourceSize</key>
<string>{128,112}</string>
<key>textureRect</key>
<string>{{678,980},{128,112}}</string>
<string>{{806,743},{128,112}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -634,37 +634,112 @@
<key>textureRotated</key>
<false/>
</dict>
<key>Dashing_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{114,112}</string>
<key>spriteSourceSize</key>
<string>{114,112}</string>
<key>textureRect</key>
<string>{{806,1037},{114,112}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Dashing_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{114,112}</string>
<key>spriteSourceSize</key>
<string>{114,112}</string>
<key>textureRect</key>
<string>{{384,1213},{114,112}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Dashing_3.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{114,112}</string>
<key>spriteSourceSize</key>
<string>{114,112}</string>
<key>textureRect</key>
<string>{{464,1327},{114,112}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Dashing_4.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{114,112}</string>
<key>spriteSourceSize</key>
<string>{114,112}</string>
<key>textureRect</key>
<string>{{496,1213},{114,112}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Dashing_5.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{114,112}</string>
<key>spriteSourceSize</key>
<string>{114,112}</string>
<key>textureRect</key>
<string>{{464,1327},{114,112}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Dashing_6.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{114,112}</string>
<key>spriteSourceSize</key>
<string>{114,112}</string>
<key>textureRect</key>
<string>{{576,1327},{114,112}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Dashing_7.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{114,112}</string>
<key>spriteSourceSize</key>
<string>{114,112}</string>
<key>textureRect</key>
<string>{{688,1043},{114,112}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>GetUp1_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{128,118}</string>
<key>spriteSourceSize</key>
<string>{128,118}</string>
<key>textureRect</key>
<string>{{806,791},{128,118}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>GetUp1_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{128,118}</string>
<key>spriteSourceSize</key>
<string>{128,118}</string>
<key>textureRect</key>
<string>{{0,846},{128,118}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>GetUp1_3.png</key>
<dict>
<key>aliases</key>
<array/>
@@ -679,6 +754,36 @@
<key>textureRotated</key>
<false/>
</dict>
<key>GetUp1_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{128,118}</string>
<key>spriteSourceSize</key>
<string>{128,118}</string>
<key>textureRect</key>
<string>{{0,958},{128,118}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>GetUp1_3.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{128,118}</string>
<key>spriteSourceSize</key>
<string>{128,118}</string>
<key>textureRect</key>
<string>{{384,753},{128,118}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>GetUp1_4.png</key>
<dict>
<key>aliases</key>
@@ -690,7 +795,7 @@
<key>spriteSourceSize</key>
<string>{128,118}</string>
<key>textureRect</key>
<string>{{326,753},{128,118}}</string>
<string>{{678,631},{128,118}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -705,7 +810,7 @@
<key>spriteSourceSize</key>
<string>{128,118}</string>
<key>textureRect</key>
<string>{{454,753},{128,118}}</string>
<string>{{384,871},{128,118}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -720,7 +825,7 @@
<key>spriteSourceSize</key>
<string>{128,118}</string>
<key>textureRect</key>
<string>{{678,862},{128,118}}</string>
<string>{{256,872},{128,118}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -735,7 +840,7 @@
<key>spriteSourceSize</key>
<string>{128,118}</string>
<key>textureRect</key>
<string>{{806,909},{128,118}}</string>
<string>{{128,964},{128,118}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -750,7 +855,7 @@
<key>spriteSourceSize</key>
<string>{70,128}</string>
<key>textureRect</key>
<string>{{256,489},{70,128}}</string>
<string>{{608,531},{70,128}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -765,7 +870,7 @@
<key>spriteSourceSize</key>
<string>{70,128}</string>
<key>textureRect</key>
<string>{{256,617},{70,128}}</string>
<string>{{608,659},{70,128}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -780,7 +885,7 @@
<key>spriteSourceSize</key>
<string>{70,128}</string>
<key>textureRect</key>
<string>{{256,745},{70,128}}</string>
<string>{{608,787},{70,128}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -795,7 +900,7 @@
<key>spriteSourceSize</key>
<string>{70,128}</string>
<key>textureRect</key>
<string>{{256,873},{70,128}}</string>
<string>{{608,915},{70,128}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -810,9 +915,9 @@
<key>spriteSourceSize</key>
<string>{70,128}</string>
<key>textureRect</key>
<string>{{112,1200},{70,128}}</string>
<string>{{128,1290},{70,128}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>Idle1_14.png</key>
<dict>
@@ -825,9 +930,9 @@
<key>spriteSourceSize</key>
<string>{70,128}</string>
<key>textureRect</key>
<string>{{182,1200},{70,128}}</string>
<string>{{0,1300},{70,128}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>Idle1_15.png</key>
<dict>
@@ -840,9 +945,9 @@
<key>spriteSourceSize</key>
<string>{70,128}</string>
<key>textureRect</key>
<string>{{252,1200},{70,128}}</string>
<string>{{0,1370},{70,128}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>Idle1_2.png</key>
<dict>
@@ -855,9 +960,9 @@
<key>spriteSourceSize</key>
<string>{70,128}</string>
<key>textureRect</key>
<string>{{252,1200},{70,128}}</string>
<string>{{0,1370},{70,128}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>Idle1_3.png</key>
<dict>
@@ -870,9 +975,9 @@
<key>spriteSourceSize</key>
<string>{70,128}</string>
<key>textureRect</key>
<string>{{182,1200},{70,128}}</string>
<string>{{0,1300},{70,128}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>Idle1_4.png</key>
<dict>
@@ -885,9 +990,9 @@
<key>spriteSourceSize</key>
<string>{70,128}</string>
<key>textureRect</key>
<string>{{112,1200},{70,128}}</string>
<string>{{128,1290},{70,128}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>Idle1_5.png</key>
<dict>
@@ -900,7 +1005,7 @@
<key>spriteSourceSize</key>
<string>{70,128}</string>
<key>textureRect</key>
<string>{{256,873},{70,128}}</string>
<string>{{608,915},{70,128}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -915,7 +1020,7 @@
<key>spriteSourceSize</key>
<string>{70,128}</string>
<key>textureRect</key>
<string>{{256,745},{70,128}}</string>
<string>{{608,787},{70,128}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -930,7 +1035,7 @@
<key>spriteSourceSize</key>
<string>{70,128}</string>
<key>textureRect</key>
<string>{{256,617},{70,128}}</string>
<string>{{608,659},{70,128}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -945,9 +1050,9 @@
<key>spriteSourceSize</key>
<string>{70,128}</string>
<key>textureRect</key>
<string>{{322,1200},{70,128}}</string>
<string>{{806,967},{70,128}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>Idle1_9.png</key>
<dict>
@@ -960,7 +1065,7 @@
<key>spriteSourceSize</key>
<string>{70,128}</string>
<key>textureRect</key>
<string>{{528,1043},{70,128}}</string>
<string>{{678,973},{70,128}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -975,7 +1080,7 @@
<key>spriteSourceSize</key>
<string>{112,96}</string>
<key>textureRect</key>
<string>{{128,1092},{112,96}}</string>
<string>{{128,1360},{112,96}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1005,7 +1110,7 @@
<key>spriteSourceSize</key>
<string>{144,112}</string>
<key>textureRect</key>
<string>{{680,512},{144,112}}</string>
<string>{{0,489},{144,112}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1020,7 +1125,7 @@
<key>spriteSourceSize</key>
<string>{128,112}</string>
<key>textureRect</key>
<string>{{806,1027},{128,112}}</string>
<string>{{678,749},{128,112}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1035,7 +1140,7 @@
<key>spriteSourceSize</key>
<string>{96,96}</string>
<key>textureRect</key>
<string>{{792,1139},{96,96}}</string>
<string>{{784,1357},{96,96}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1050,7 +1155,7 @@
<key>spriteSourceSize</key>
<string>{80,96}</string>
<key>textureRect</key>
<string>{{934,1104},{80,96}}</string>
<string>{{934,976},{80,96}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1065,7 +1170,7 @@
<key>spriteSourceSize</key>
<string>{112,112}</string>
<key>textureRect</key>
<string>{{352,1081},{112,112}}</string>
<string>{{688,1155},{112,112}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1080,7 +1185,7 @@
<key>spriteSourceSize</key>
<string>{128,96}</string>
<key>textureRect</key>
<string>{{0,1092},{128,96}}</string>
<string>{{256,1102},{128,96}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1095,7 +1200,7 @@
<key>spriteSourceSize</key>
<string>{80,112}</string>
<key>textureRect</key>
<string>{{934,768},{80,112}}</string>
<string>{{934,640},{80,112}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1110,7 +1215,7 @@
<key>spriteSourceSize</key>
<string>{80,112}</string>
<key>textureRect</key>
<string>{{934,880},{80,112}}</string>
<string>{{934,752},{80,112}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1125,9 +1230,9 @@
<key>spriteSourceSize</key>
<string>{64,128}</string>
<key>textureRect</key>
<string>{{464,1079},{64,128}}</string>
<string>{{256,1294},{64,128}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>InAirIdle1_3.png</key>
<dict>
@@ -1140,7 +1245,7 @@
<key>spriteSourceSize</key>
<string>{80,112}</string>
<key>textureRect</key>
<string>{{934,992},{80,112}}</string>
<string>{{934,864},{80,112}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1155,9 +1260,9 @@
<key>spriteSourceSize</key>
<string>{80,96}</string>
<key>textureRect</key>
<string>{{224,1001},{80,96}}</string>
<string>{{608,1043},{80,96}}</string>
<key>textureRotated</key>
<true/>
<false/>
</dict>
<key>InAirIdle1_5.png</key>
<dict>
@@ -1170,9 +1275,9 @@
<key>spriteSourceSize</key>
<string>{80,96}</string>
<key>textureRect</key>
<string>{{320,1001},{80,96}}</string>
<string>{{608,1139},{80,96}}</string>
<key>textureRotated</key>
<true/>
<false/>
</dict>
<key>InAirIdle1_6.png</key>
<dict>
@@ -1185,9 +1290,9 @@
<key>spriteSourceSize</key>
<string>{80,96}</string>
<key>textureRect</key>
<string>{{792,1235},{80,96}}</string>
<string>{{688,1267},{80,96}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>InAirIdle1_7.png</key>
<dict>
@@ -1200,9 +1305,9 @@
<key>spriteSourceSize</key>
<string>{96,112}</string>
<key>textureRect</key>
<string>{{600,1209},{96,112}}</string>
<string>{{912,1296},{96,112}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>InAirIdle1_8.png</key>
<dict>
@@ -1215,9 +1320,9 @@
<key>spriteSourceSize</key>
<string>{96,128}</string>
<key>textureRect</key>
<string>{{582,787},{96,128}}</string>
<string>{{128,1194},{96,128}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>InAirIdle1_9.png</key>
<dict>
@@ -1230,9 +1335,9 @@
<key>spriteSourceSize</key>
<string>{96,128}</string>
<key>textureRect</key>
<string>{{582,915},{96,128}}</string>
<string>{{256,1198},{96,128}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>LayDown1_1.png</key>
<dict>
@@ -1264,6 +1369,96 @@
<key>textureRotated</key>
<false/>
</dict>
<key>OnWall1_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{112,97}</string>
<key>spriteSourceSize</key>
<string>{112,97}</string>
<key>textureRect</key>
<string>{{840,288},{112,97}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>OnWall1_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{112,97}</string>
<key>spriteSourceSize</key>
<string>{112,97}</string>
<key>textureRect</key>
<string>{{840,400},{112,97}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>OnWall1_3.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{112,97}</string>
<key>spriteSourceSize</key>
<string>{112,97}</string>
<key>textureRect</key>
<string>{{840,400},{112,97}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>TurnAround1_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{112,128}</string>
<key>spriteSourceSize</key>
<string>{112,128}</string>
<key>textureRect</key>
<string>{{806,855},{112,128}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>TurnAround1_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{112,128}</string>
<key>spriteSourceSize</key>
<string>{112,128}</string>
<key>textureRect</key>
<string>{{678,861},{112,128}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>TurnAround1_3.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{112,128}</string>
<key>spriteSourceSize</key>
<string>{112,128}</string>
<key>textureRect</key>
<string>{{384,1101},{112,128}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Walking_1.png</key>
<dict>
<key>aliases</key>
@@ -1275,7 +1470,7 @@
<key>spriteSourceSize</key>
<string>{119,128}</string>
<key>textureRect</key>
<string>{{0,489},{119,128}}</string>
<string>{{144,489},{119,128}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -1290,7 +1485,7 @@
<key>spriteSourceSize</key>
<string>{119,128}</string>
<key>textureRect</key>
<string>{{128,489},{119,128}}</string>
<string>{{0,601},{119,128}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -1305,7 +1500,7 @@
<key>spriteSourceSize</key>
<string>{119,128}</string>
<key>textureRect</key>
<string>{{0,608},{119,128}}</string>
<string>{{272,515},{119,128}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -1335,7 +1530,7 @@
<key>spriteSourceSize</key>
<string>{119,128}</string>
<key>textureRect</key>
<string>{{326,515},{119,128}}</string>
<string>{{0,720},{119,128}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -1350,7 +1545,7 @@
<key>spriteSourceSize</key>
<string>{119,128}</string>
<key>textureRect</key>
<string>{{454,515},{119,128}}</string>
<string>{{400,515},{119,128}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -1365,7 +1560,7 @@
<key>spriteSourceSize</key>
<string>{119,128}</string>
<key>textureRect</key>
<string>{{678,624},{119,128}}</string>
<string>{{256,634},{119,128}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -1380,7 +1575,7 @@
<key>spriteSourceSize</key>
<string>{119,128}</string>
<key>textureRect</key>
<string>{{806,672},{119,128}}</string>
<string>{{128,727},{119,128}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -1395,7 +1590,7 @@
<key>spriteSourceSize</key>
<string>{119,128}</string>
<key>textureRect</key>
<string>{{0,727},{119,128}}</string>
<string>{{0,839},{119,128}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -1410,7 +1605,7 @@
<key>spriteSourceSize</key>
<string>{119,128}</string>
<key>textureRect</key>
<string>{{128,727},{119,128}}</string>
<string>{{384,634},{119,128}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -1425,7 +1620,7 @@
<key>spriteSourceSize</key>
<string>{119,128}</string>
<key>textureRect</key>
<string>{{326,634},{119,128}}</string>
<string>{{680,512},{119,128}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -1440,7 +1635,7 @@
<key>spriteSourceSize</key>
<string>{119,128}</string>
<key>textureRect</key>
<string>{{454,634},{119,128}}</string>
<string>{{808,512},{119,128}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -1455,7 +1650,7 @@
<key>spriteSourceSize</key>
<string>{119,128}</string>
<key>textureRect</key>
<string>{{678,743},{119,128}}</string>
<string>{{256,753},{119,128}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -1471,9 +1666,9 @@
<key>realTextureFileName</key>
<string>KnifeGirl.png</string>
<key>size</key>
<string>{1020,1331}</string>
<string>{1024,1456}</string>
<key>smartupdate</key>
<string>$TexturePacker:SmartUpdate:9514b6b35473e14baf98f68515bcb817:1aae9dd4a8024ce783fdab093a39672a:1ae107e0c6667a1ecb5ed98687517e0e$</string>
<string>$TexturePacker:SmartUpdate:8fd7507b5e24a1de6da5e4a6c568fcd3:d861e924a13180a640774a9c85662e57:1ae107e0c6667a1ecb5ed98687517e0e$</string>
<key>textureFileName</key>
<string>KnifeGirl.png</string>
</dict>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 119 KiB

View File

@@ -0,0 +1,37 @@
{
"__type__": "cc.AnimationClip",
"_name": "OnWall",
"_objFlags": 0,
"_native": "",
"_duration": 0.26666666666666666,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "c18886db-8116-4602-84f2-51652a90269a"
}
},
{
"frame": 0.13333333333333333,
"value": {
"__uuid__": "0d81cbf0-dff8-4672-99b3-2ec8055c6931"
}
},
{
"frame": 0.25,
"value": {
"__uuid__": "a183e740-3c2d-4890-8430-39a00f55f446"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,5 @@
{
"ver": "2.1.0",
"uuid": "411f964a-4dd8-424c-b2e2-d92b10474ce2",
"subMetas": {}
}

View File

@@ -0,0 +1,43 @@
{
"__type__": "cc.AnimationClip",
"_name": "TurnAround1",
"_objFlags": 0,
"_native": "",
"_duration": 0.15,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "28ee1f29-e538-4d36-bb5c-275f9e3b392b"
}
},
{
"frame": 0.03333333333333333,
"value": {
"__uuid__": "211a73bb-31d7-4e6c-901e-f6939d9214e0"
}
},
{
"frame": 0.08333333333333333,
"value": {
"__uuid__": "048c41dc-fc00-4bc4-8041-6003e7c2b6e4"
}
},
{
"frame": 0.13333333333333333,
"value": {
"__uuid__": "9435195e-4560-495e-b1ae-083c0c87e8a0"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,5 @@
{
"ver": "2.1.0",
"uuid": "e906322d-a08b-4477-a2e9-98acd42fa034",
"subMetas": {}
}

View File

@@ -3,7 +3,7 @@
"_name": "Walking",
"_objFlags": 0,
"_native": "",
"_duration": 1.5166666666666666,
"_duration": 0.6333333333333333,
"sample": 60,
"speed": 1.2,
"wrapMode": 2,
@@ -13,78 +13,78 @@
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "c3b14ecc-a6d9-4cb3-8637-ca7b407a0f5c"
}
},
{
"frame": 0.08333333333333333,
"value": {
"__uuid__": "9435195e-4560-495e-b1ae-083c0c87e8a0"
}
},
{
"frame": 0.18333333333333332,
"frame": 0.06666666666666667,
"value": {
"__uuid__": "ec048360-7a17-4f22-ba52-eb86ec1acae8"
}
},
{
"frame": 0.2833333333333333,
"frame": 0.11666666666666667,
"value": {
"__uuid__": "82bb81e3-667c-4280-8710-211f4904ef2f"
}
},
{
"frame": 0.4,
"frame": 0.16666666666666666,
"value": {
"__uuid__": "c3b14ecc-a6d9-4cb3-8637-ca7b407a0f5c"
}
},
{
"frame": 0.21666666666666667,
"value": {
"__uuid__": "f958fb7f-ef5a-4918-81f3-564004572f45"
}
},
{
"frame": 0.5333333333333333,
"frame": 0.26666666666666666,
"value": {
"__uuid__": "8a0ecf92-db26-4206-9a80-20e749055def"
}
},
{
"frame": 0.65,
"frame": 0.31666666666666665,
"value": {
"__uuid__": "942f2e02-a700-4fbf-877e-08c93e4d4010"
}
},
{
"frame": 0.7666666666666667,
"frame": 0.36666666666666664,
"value": {
"__uuid__": "30546064-1a11-499e-8523-a82c83951c73"
}
},
{
"frame": 0.9,
"frame": 0.4166666666666667,
"value": {
"__uuid__": "515bb75f-7a1f-4500-8aa9-c895915ce19f"
}
},
{
"frame": 1.0333333333333334,
"frame": 0.4666666666666667,
"value": {
"__uuid__": "9100da6b-7582-4afb-9698-3d67d3b2012d"
}
},
{
"frame": 1.2166666666666666,
"frame": 0.5166666666666667,
"value": {
"__uuid__": "1257f72d-0cb3-4750-ae70-13c2d8eb2269"
}
},
{
"frame": 1.3833333333333333,
"frame": 0.5666666666666667,
"value": {
"__uuid__": "1d34b6db-27ba-4e26-864d-0f00d501765e"
}
},
{
"frame": 1.5,
"frame": 0.6166666666666667,
"value": {
"__uuid__": "c317a75a-52c0-4c38-9300-a064cbf4efb3"
}

View File

@@ -3,7 +3,7 @@
"_name": "Atk3",
"_objFlags": 0,
"_native": "",
"_duration": 0.6333333333333333,
"_duration": 0.5333333333333333,
"sample": 60,
"speed": 1,
"wrapMode": 1,
@@ -13,84 +13,72 @@
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "318745eb-06b1-4e7f-88d1-e23e02d99e67"
}
},
{
"frame": 0.06666666666666667,
"value": {
"__uuid__": "a64b6f59-fa72-4f5d-89dc-81a469244ea5"
}
},
{
"frame": 0.11666666666666667,
"value": {
"__uuid__": "f800d4a1-2396-4aa5-a578-11481db1d8bf"
}
},
{
"frame": 0.16666666666666666,
"value": {
"__uuid__": "d97f6a5f-8e63-40d7-bd14-9dc71e15e5db"
}
},
{
"frame": 0.23333333333333334,
"frame": 0.03333333333333333,
"value": {
"__uuid__": "196bcbf9-e89f-4b26-b736-73e2fa787e50"
}
},
{
"frame": 0.3,
"frame": 0.08333333333333333,
"value": {
"__uuid__": "3229e023-e63d-4a4e-af72-2b1409ea43c5"
}
},
{
"frame": 0.36666666666666664,
"frame": 0.11666666666666667,
"value": {
"__uuid__": "e2d6e8b8-b468-4edb-b8c3-860bd85ebeae"
}
},
{
"frame": 0.4166666666666667,
"frame": 0.16666666666666666,
"value": {
"__uuid__": "318745eb-06b1-4e7f-88d1-e23e02d99e67"
}
},
{
"frame": 0.21666666666666667,
"value": {
"__uuid__": "bba6f088-0e1f-4a12-9872-41670be1152a"
}
},
{
"frame": 0.45,
"frame": 0.26666666666666666,
"value": {
"__uuid__": "2c5de5b2-9009-48fa-bef4-ae34cc94f876"
}
},
{
"frame": 0.48333333333333334,
"frame": 0.31666666666666665,
"value": {
"__uuid__": "6f27b252-6eaf-4b4b-9c5a-46ba899e4845"
}
},
{
"frame": 0.5166666666666667,
"frame": 0.36666666666666664,
"value": {
"__uuid__": "4ebd5c60-efa6-4950-a4c8-74a7a8517333"
}
},
{
"frame": 0.55,
"frame": 0.4166666666666667,
"value": {
"__uuid__": "a207290f-4556-4adb-8a11-e1d5ba342550"
}
},
{
"frame": 0.5833333333333334,
"frame": 0.4666666666666667,
"value": {
"__uuid__": "e9d442d2-981d-437d-87c0-085162017de7"
}
},
{
"frame": 0.6166666666666667,
"frame": 0.5166666666666667,
"value": {
"__uuid__": "9b4d5c8c-5ec0-4fd7-a45e-6b0bc8ff9119"
}

View File

@@ -0,0 +1,85 @@
{
"__type__": "cc.AnimationClip",
"_name": "Atk5",
"_objFlags": 0,
"_native": "",
"_duration": 1.0166666666666666,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "6aa88bb9-0427-496f-ae7d-dc06410e904e"
}
},
{
"frame": 0.08333333333333333,
"value": {
"__uuid__": "cdc65f83-c526-48b6-8a96-758b098568fe"
}
},
{
"frame": 0.16666666666666666,
"value": {
"__uuid__": "927636af-2d1d-4801-a546-857f5eeb256d"
}
},
{
"frame": 0.26666666666666666,
"value": {
"__uuid__": "2aeeb833-9151-4160-9775-9e08a376fd63"
}
},
{
"frame": 0.36666666666666664,
"value": {
"__uuid__": "2bd1de9e-30e5-4bc5-b6c3-5c286754b0b7"
}
},
{
"frame": 0.4666666666666667,
"value": {
"__uuid__": "15a6ebb3-289a-46fb-ac94-f6efa0d90510"
}
},
{
"frame": 0.5833333333333334,
"value": {
"__uuid__": "6ca922c0-cb62-4b1b-8773-79685a58bbd6"
}
},
{
"frame": 0.7,
"value": {
"__uuid__": "d60ceb6f-3a45-47dd-8d3f-bcfe8c919d85"
}
},
{
"frame": 0.8,
"value": {
"__uuid__": "c313f6a1-e0fa-4321-8336-c32f471b2592"
}
},
{
"frame": 0.9,
"value": {
"__uuid__": "bb886d03-7f3e-45c8-acfd-393091f09adb"
}
},
{
"frame": 1,
"value": {
"__uuid__": "1be255c3-f8c9-43ae-be68-2e500e7f1125"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,5 @@
{
"ver": "2.1.0",
"uuid": "0abbd156-980e-475e-9994-3c958bd913fc",
"subMetas": {}
}

View File

@@ -3,7 +3,7 @@
"_name": "InAirIdle1ByJump",
"_objFlags": 0,
"_native": "",
"_duration": 0.7833333333333333,
"_duration": 0.5833333333333334,
"sample": 60,
"speed": 1,
"wrapMode": 1,
@@ -18,67 +18,67 @@
}
},
{
"frame": 0.05,
"frame": 0.03333333333333333,
"value": {
"__uuid__": "06d18871-0cb6-41eb-a484-5c6a4c04d5d5"
}
},
{
"frame": 0.11666666666666667,
"frame": 0.06666666666666667,
"value": {
"__uuid__": "f298ff82-ad9d-4945-ab19-14c3e3d54c95"
}
},
{
"frame": 0.18333333333333332,
"frame": 0.11666666666666667,
"value": {
"__uuid__": "bb5924a6-40cf-4e43-8c94-e51b27861656"
}
},
{
"frame": 0.25,
"frame": 0.16666666666666666,
"value": {
"__uuid__": "fc4b5181-77af-44ec-836e-c14eec8d20c4"
}
},
{
"frame": 0.3333333333333333,
"frame": 0.21666666666666667,
"value": {
"__uuid__": "5ddd3db3-79b2-4f0c-bb76-2446801ff665"
}
},
{
"frame": 0.4166666666666667,
"frame": 0.26666666666666666,
"value": {
"__uuid__": "032785ce-c911-479b-be1c-2e0899a586d0"
}
},
{
"frame": 0.48333333333333334,
"frame": 0.31666666666666665,
"value": {
"__uuid__": "d651269d-1c08-49f8-bc38-d301bf26b0e1"
}
},
{
"frame": 0.5666666666666667,
"frame": 0.36666666666666664,
"value": {
"__uuid__": "e270563e-d98d-4a80-82db-837183053ae3"
}
},
{
"frame": 0.6333333333333333,
"frame": 0.43333333333333335,
"value": {
"__uuid__": "aec31ef8-46dc-4f0e-9cba-18f6c96c5c33"
}
},
{
"frame": 0.7,
"frame": 0.5,
"value": {
"__uuid__": "e64b3a8d-41a9-45f6-9aeb-9e49b6317080"
}
},
{
"frame": 0.7666666666666667,
"frame": 0.5666666666666667,
"value": {
"__uuid__": "cf886091-24a9-4cfb-8cb9-e3db977035ab"
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 KiB

After

Width:  |  Height:  |  Size: 269 KiB

View File

@@ -0,0 +1,43 @@
{
"__type__": "cc.AnimationClip",
"_name": "TurnAround1",
"_objFlags": 0,
"_native": "",
"_duration": 0.15,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "ee5e05fa-b515-470f-bc3c-43544f02cb92"
}
},
{
"frame": 0.03333333333333333,
"value": {
"__uuid__": "ffa521b6-118e-46e8-be1c-51cc54381ec8"
}
},
{
"frame": 0.08333333333333333,
"value": {
"__uuid__": "0b27d2c9-c5a3-4020-adbe-0297c1ba3aeb"
}
},
{
"frame": 0.13333333333333333,
"value": {
"__uuid__": "a47f518e-62fb-4549-8897-4f2d387bd145"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,5 @@
{
"ver": "2.1.0",
"uuid": "edd23b2f-1caa-4836-88a7-e4af1f26743e",
"subMetas": {}
}

View File

@@ -15,7 +15,7 @@
<key>spriteSourceSize</key>
<string>{62,92}</string>
<key>textureRect</key>
<string>{{1277,188},{62,92}}</string>
<string>{{1307,188},{62,92}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -30,7 +30,7 @@
<key>spriteSourceSize</key>
<string>{77,99}</string>
<key>textureRect</key>
<string>{{748,0},{77,99}}</string>
<string>{{782,101},{77,99}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -45,7 +45,7 @@
<key>spriteSourceSize</key>
<string>{112,99}</string>
<key>textureRect</key>
<string>{{408,348},{112,99}}</string>
<string>{{381,360},{112,99}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -60,7 +60,7 @@
<key>spriteSourceSize</key>
<string>{96,100}</string>
<key>textureRect</key>
<string>{{664,315},{96,100}}</string>
<string>{{704,312},{96,100}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -75,7 +75,7 @@
<key>spriteSourceSize</key>
<string>{62,92}</string>
<key>textureRect</key>
<string>{{1277,188},{62,92}}</string>
<string>{{1307,188},{62,92}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -90,7 +90,7 @@
<key>spriteSourceSize</key>
<string>{58,97}</string>
<key>textureRect</key>
<string>{{1023,194},{58,97}}</string>
<string>{{983,388},{58,97}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -105,9 +105,9 @@
<key>spriteSourceSize</key>
<string>{60,90}</string>
<key>textureRect</key>
<string>{{1393,141},{60,90}}</string>
<string>{{1424,0},{60,90}}</string>
<key>textureRotated</key>
<true/>
<false/>
</dict>
<key>Atk2_2.png</key>
<dict>
@@ -120,7 +120,7 @@
<key>spriteSourceSize</key>
<string>{84,96}</string>
<key>textureRect</key>
<string>{{1087,97},{84,96}}</string>
<string>{{1082,291},{84,96}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -135,7 +135,7 @@
<key>spriteSourceSize</key>
<string>{55,100}</string>
<key>textureRect</key>
<string>{{731,101},{55,100}}</string>
<string>{{738,206},{55,100}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -150,9 +150,9 @@
<key>spriteSourceSize</key>
<string>{63,100}</string>
<key>textureRect</key>
<string>{{717,206},{63,100}}</string>
<string>{{0,437},{63,100}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>Atk2_5.png</key>
<dict>
@@ -165,7 +165,7 @@
<key>spriteSourceSize</key>
<string>{66,101}</string>
<key>textureRect</key>
<string>{{682,0},{66,101}}</string>
<string>{{755,0},{66,101}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -180,7 +180,7 @@
<key>spriteSourceSize</key>
<string>{80,95}</string>
<key>textureRect</key>
<string>{{1126,0},{80,95}}</string>
<string>{{1099,387},{80,95}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -195,7 +195,7 @@
<key>spriteSourceSize</key>
<string>{116,109}</string>
<key>textureRect</key>
<string>{{315,119},{116,109}}</string>
<string>{{336,244},{116,109}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -210,7 +210,7 @@
<key>spriteSourceSize</key>
<string>{102,96}</string>
<key>textureRect</key>
<string>{{621,213},{102,96}}</string>
<string>{{608,325},{102,96}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -225,9 +225,9 @@
<key>spriteSourceSize</key>
<string>{75,102}</string>
<key>textureRect</key>
<string>{{139,421},{75,102}}</string>
<string>{{663,210},{75,102}}</string>
<key>textureRotated</key>
<true/>
<false/>
</dict>
<key>Atk3_0.png</key>
<dict>
@@ -240,7 +240,7 @@
<key>spriteSourceSize</key>
<string>{66,109}</string>
<key>textureRect</key>
<string>{{469,110},{66,109}}</string>
<string>{{480,339},{66,109}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -255,7 +255,7 @@
<key>spriteSourceSize</key>
<string>{66,113}</string>
<key>textureRect</key>
<string>{{355,235},{66,113}}</string>
<string>{{403,114},{66,113}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -330,7 +330,7 @@
<key>spriteSourceSize</key>
<string>{78,131}</string>
<key>textureRect</key>
<string>{{137,290},{78,131}}</string>
<string>{{78,0},{78,131}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -345,9 +345,9 @@
<key>spriteSourceSize</key>
<string>{59,139}</string>
<key>textureRect</key>
<string>{{0,437},{59,139}}</string>
<string>{{78,290},{59,139}}</string>
<key>textureRotated</key>
<true/>
<false/>
</dict>
<key>Atk3_8.png</key>
<dict>
@@ -360,7 +360,7 @@
<key>spriteSourceSize</key>
<string>{59,139}</string>
<key>textureRect</key>
<string>{{78,290},{59,139}}</string>
<string>{{137,290},{59,139}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -375,9 +375,9 @@
<key>spriteSourceSize</key>
<string>{62,97}</string>
<key>textureRect</key>
<string>{{507,434},{62,97}}</string>
<string>{{962,291},{62,97}}</string>
<key>textureRotated</key>
<true/>
<false/>
</dict>
<key>Atked1_1.png</key>
<dict>
@@ -390,9 +390,9 @@
<key>spriteSourceSize</key>
<string>{73,95}</string>
<key>textureRect</key>
<string>{{1171,95},{73,95}}</string>
<string>{{641,427},{73,95}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>Atked1_2.png</key>
<dict>
@@ -405,7 +405,7 @@
<key>spriteSourceSize</key>
<string>{90,89}</string>
<key>textureRect</key>
<string>{{1324,0},{90,89}}</string>
<string>{{1335,0},{90,89}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -420,7 +420,7 @@
<key>spriteSourceSize</key>
<string>{95,80}</string>
<key>textureRect</key>
<string>{{1084,291},{95,80}}</string>
<string>{{1168,193},{95,80}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -435,7 +435,7 @@
<key>spriteSourceSize</key>
<string>{80,95}</string>
<key>textureRect</key>
<string>{{1010,388},{80,95}}</string>
<string>{{1166,290},{80,95}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -450,7 +450,7 @@
<key>spriteSourceSize</key>
<string>{83,92}</string>
<key>textureRect</key>
<string>{{1208,382},{83,92}}</string>
<string>{{1299,382},{83,92}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -465,7 +465,7 @@
<key>spriteSourceSize</key>
<string>{92,83}</string>
<key>textureRect</key>
<string>{{1224,284},{92,83}}</string>
<string>{{1306,284},{92,83}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -480,7 +480,7 @@
<key>spriteSourceSize</key>
<string>{112,45}</string>
<key>textureRect</key>
<string>{{424,115},{112,45}}</string>
<string>{{469,112},{112,45}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -495,7 +495,7 @@
<key>spriteSourceSize</key>
<string>{88,69}</string>
<key>textureRect</key>
<string>{{604,427},{88,69}}</string>
<string>{{1443,222},{88,69}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -510,7 +510,7 @@
<key>spriteSourceSize</key>
<string>{91,90}</string>
<key>textureRect</key>
<string>{{1303,93},{91,90}}</string>
<string>{{1313,93},{91,90}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -525,7 +525,7 @@
<key>spriteSourceSize</key>
<string>{120,93}</string>
<key>textureRect</key>
<string>{{222,123},{120,93}}</string>
<string>{{254,124},{120,93}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -540,9 +540,9 @@
<key>spriteSourceSize</key>
<string>{100,112}</string>
<key>textureRect</key>
<string>{{241,396},{100,112}}</string>
<string>{{408,0},{100,112}}</string>
<key>textureRotated</key>
<true/>
<false/>
</dict>
<key>GetUp1_5.png</key>
<dict>
@@ -555,7 +555,7 @@
<key>spriteSourceSize</key>
<string>{106,93}</string>
<key>textureRect</key>
<string>{{507,328},{106,93}}</string>
<string>{{570,219},{106,93}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -570,7 +570,7 @@
<key>spriteSourceSize</key>
<string>{106,79}</string>
<key>textureRect</key>
<string>{{542,217},{106,79}}</string>
<string>{{571,108},{106,79}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -585,7 +585,7 @@
<key>spriteSourceSize</key>
<string>{73,87}</string>
<key>textureRect</key>
<string>{{1307,280},{73,87}}</string>
<string>{{1382,376},{73,87}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -600,9 +600,9 @@
<key>spriteSourceSize</key>
<string>{67,90}</string>
<key>textureRect</key>
<string>{{1413,74},{67,90}}</string>
<string>{{1403,90},{67,90}}</string>
<key>textureRotated</key>
<true/>
<false/>
</dict>
<key>GetUp1_9.png</key>
<dict>
@@ -615,7 +615,7 @@
<key>spriteSourceSize</key>
<string>{58,97}</string>
<key>textureRect</key>
<string>{{1023,194},{58,97}}</string>
<string>{{983,388},{58,97}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -630,7 +630,7 @@
<key>spriteSourceSize</key>
<string>{58,95}</string>
<key>textureRect</key>
<string>{{1090,386},{58,95}}</string>
<string>{{1219,0},{58,95}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -645,7 +645,7 @@
<key>spriteSourceSize</key>
<string>{58,97}</string>
<key>textureRect</key>
<string>{{1029,97},{58,97}}</string>
<string>{{1024,291},{58,97}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -660,7 +660,7 @@
<key>spriteSourceSize</key>
<string>{60,94}</string>
<key>textureRect</key>
<string>{{1148,386},{60,94}}</string>
<string>{{1179,385},{60,94}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -675,7 +675,7 @@
<key>spriteSourceSize</key>
<string>{58,97}</string>
<key>textureRect</key>
<string>{{1081,194},{58,97}}</string>
<string>{{1036,194},{58,97}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -690,7 +690,7 @@
<key>spriteSourceSize</key>
<string>{58,97}</string>
<key>textureRect</key>
<string>{{1068,0},{58,97}}</string>
<string>{{1041,388},{58,97}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -705,9 +705,9 @@
<key>spriteSourceSize</key>
<string>{60,95}</string>
<key>textureRect</key>
<string>{{1206,0},{60,95}}</string>
<string>{{546,440},{60,95}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>Idle1_5.png</key>
<dict>
@@ -720,7 +720,7 @@
<key>spriteSourceSize</key>
<string>{60,94}</string>
<key>textureRect</key>
<string>{{1164,288},{60,94}}</string>
<string>{{1239,385},{60,94}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -735,7 +735,7 @@
<key>spriteSourceSize</key>
<string>{59,93}</string>
<key>textureRect</key>
<string>{{789,403},{59,93}}</string>
<string>{{1248,191},{59,93}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -750,7 +750,7 @@
<key>spriteSourceSize</key>
<string>{58,93}</string>
<key>textureRect</key>
<string>{{1266,0},{58,93}}</string>
<string>{{1277,0},{58,93}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -765,7 +765,7 @@
<key>spriteSourceSize</key>
<string>{59,93}</string>
<key>textureRect</key>
<string>{{1244,95},{59,93}}</string>
<string>{{1254,95},{59,93}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -780,7 +780,7 @@
<key>spriteSourceSize</key>
<string>{60,94}</string>
<key>textureRect</key>
<string>{{1217,190},{60,94}}</string>
<string>{{1246,288},{60,94}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -795,7 +795,7 @@
<key>spriteSourceSize</key>
<string>{77,68}</string>
<key>textureRect</key>
<string>{{1437,417},{77,68}}</string>
<string>{{1473,291},{77,68}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -810,7 +810,7 @@
<key>spriteSourceSize</key>
<string>{118,76}</string>
<key>textureRect</key>
<string>{{215,278},{118,76}}</string>
<string>{{196,284},{118,76}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -825,7 +825,7 @@
<key>spriteSourceSize</key>
<string>{104,65}</string>
<key>textureRect</key>
<string>{{617,0},{104,65}}</string>
<string>{{650,106},{104,65}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -840,9 +840,9 @@
<key>spriteSourceSize</key>
<string>{80,66}</string>
<key>textureRect</key>
<string>{{1380,285},{80,66}}</string>
<string>{{1473,368},{80,66}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>InAirAtk1_12.png</key>
<dict>
@@ -855,7 +855,7 @@
<key>spriteSourceSize</key>
<string>{102,67}</string>
<key>textureRect</key>
<string>{{664,104},{102,67}}</string>
<string>{{715,104},{102,67}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -870,9 +870,9 @@
<key>spriteSourceSize</key>
<string>{79,66}</string>
<key>textureRect</key>
<string>{{1339,201},{79,66}}</string>
<string>{{1470,90},{79,66}}</string>
<key>textureRotated</key>
<true/>
<false/>
</dict>
<key>InAirAtk1_3.png</key>
<dict>
@@ -885,7 +885,7 @@
<key>spriteSourceSize</key>
<string>{124,64}</string>
<key>textureRect</key>
<string>{{78,0},{124,64}}</string>
<string>{{156,0},{124,64}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -900,7 +900,7 @@
<key>spriteSourceSize</key>
<string>{104,64}</string>
<key>textureRect</key>
<string>{{600,323},{104,64}}</string>
<string>{{691,0},{104,64}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -915,7 +915,7 @@
<key>spriteSourceSize</key>
<string>{79,61}</string>
<key>textureRect</key>
<string>{{1376,417},{79,61}}</string>
<string>{{1484,0},{79,61}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -930,7 +930,7 @@
<key>spriteSourceSize</key>
<string>{124,64}</string>
<key>textureRect</key>
<string>{{142,0},{124,64}}</string>
<string>{{160,124},{124,64}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -945,7 +945,7 @@
<key>spriteSourceSize</key>
<string>{106,67}</string>
<key>textureRect</key>
<string>{{597,107},{106,67}}</string>
<string>{{624,0},{106,67}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -960,7 +960,7 @@
<key>spriteSourceSize</key>
<string>{79,66}</string>
<key>textureRect</key>
<string>{{1380,351},{79,66}}</string>
<string>{{1470,156},{79,66}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -975,7 +975,7 @@
<key>spriteSourceSize</key>
<string>{118,64}</string>
<key>textureRect</key>
<string>{{291,243},{118,64}}</string>
<string>{{272,284},{118,64}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -990,9 +990,9 @@
<key>spriteSourceSize</key>
<string>{71,119}</string>
<key>textureRect</key>
<string>{{242,0},{71,119}}</string>
<string>{{100,429},{71,119}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>InAirIdle1_1.png</key>
<dict>
@@ -1005,7 +1005,7 @@
<key>spriteSourceSize</key>
<string>{71,119}</string>
<key>textureRect</key>
<string>{{313,0},{71,119}}</string>
<string>{{282,0},{71,119}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1020,7 +1020,7 @@
<key>spriteSourceSize</key>
<string>{55,114}</string>
<key>textureRect</key>
<string>{{353,361},{55,114}}</string>
<string>{{353,0},{55,114}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1035,7 +1035,7 @@
<key>spriteSourceSize</key>
<string>{62,124}</string>
<key>textureRect</key>
<string>{{160,124},{62,124}}</string>
<string>{{220,0},{62,124}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1050,9 +1050,9 @@
<key>spriteSourceSize</key>
<string>{74,90}</string>
<key>textureRect</key>
<string>{{1413,0},{74,90}}</string>
<string>{{1369,184},{74,90}}</string>
<key>textureRotated</key>
<true/>
<false/>
</dict>
<key>InAirIdle1_3.png</key>
<dict>
@@ -1065,7 +1065,7 @@
<key>spriteSourceSize</key>
<string>{110,54}</string>
<key>textureRect</key>
<string>{{440,0},{110,54}}</string>
<string>{{508,0},{110,54}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -1080,7 +1080,7 @@
<key>spriteSourceSize</key>
<string>{85,88}</string>
<key>textureRect</key>
<string>{{1291,376},{85,88}}</string>
<string>{{736,412},{85,88}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1095,7 +1095,7 @@
<key>spriteSourceSize</key>
<string>{64,112}</string>
<key>textureRect</key>
<string>{{421,235},{64,112}}</string>
<string>{{445,227},{64,112}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1110,7 +1110,7 @@
<key>spriteSourceSize</key>
<string>{62,107}</string>
<key>textureRect</key>
<string>{{555,0},{62,107}}</string>
<string>{{546,333},{62,107}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1125,9 +1125,9 @@
<key>spriteSourceSize</key>
<string>{85,84}</string>
<key>textureRect</key>
<string>{{1405,201},{85,84}}</string>
<string>{{1389,291},{85,84}}</string>
<key>textureRotated</key>
<false/>
<true/>
</dict>
<key>InAirIdle1_8.png</key>
<dict>
@@ -1140,7 +1140,7 @@
<key>spriteSourceSize</key>
<string>{109,61}</string>
<key>textureRect</key>
<string>{{494,0},{109,61}}</string>
<string>{{509,224},{109,61}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -1155,7 +1155,7 @@
<key>spriteSourceSize</key>
<string>{78,95}</string>
<key>textureRect</key>
<string>{{1139,193},{78,95}}</string>
<string>{{1176,96},{78,95}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1170,7 +1170,7 @@
<key>spriteSourceSize</key>
<string>{115,56}</string>
<key>textureRect</key>
<string>{{384,0},{115,56}}</string>
<string>{{347,119},{115,56}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -1185,7 +1185,7 @@
<key>spriteSourceSize</key>
<string>{109,57}</string>
<key>textureRect</key>
<string>{{485,219},{109,57}}</string>
<string>{{514,110},{109,57}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -1200,7 +1200,7 @@
<key>spriteSourceSize</key>
<string>{108,62}</string>
<key>textureRect</key>
<string>{{535,109},{108,62}}</string>
<string>{{562,0},{108,62}}</string>
<key>textureRotated</key>
<true/>
</dict>
@@ -1215,9 +1215,9 @@
<key>spriteSourceSize</key>
<string>{123,36}</string>
<key>textureRect</key>
<string>{{206,0},{123,36}}</string>
<string>{{160,248},{123,36}}</string>
<key>textureRotated</key>
<true/>
<false/>
</dict>
<key>LayDown1_4.png</key>
<dict>
@@ -1230,7 +1230,52 @@
<key>spriteSourceSize</key>
<string>{123,30}</string>
<key>textureRect</key>
<string>{{160,248},{123,30}}</string>
<string>{{224,124},{123,30}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>TurnAround1_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{74,96}</string>
<key>spriteSourceSize</key>
<string>{74,96}</string>
<key>textureRect</key>
<string>{{1094,194},{74,96}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>TurnAround1_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{74,96}</string>
<key>spriteSourceSize</key>
<string>{74,96}</string>
<key>textureRect</key>
<string>{{1102,97},{74,96}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>TurnAround1_3.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{74,96}</string>
<key>spriteSourceSize</key>
<string>{74,96}</string>
<key>textureRect</key>
<string>{{1145,0},{74,96}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1245,9 +1290,9 @@
<key>spriteSourceSize</key>
<string>{81,97}</string>
<key>textureRect</key>
<string>{{692,415},{81,97}}</string>
<string>{{219,402},{81,97}}</string>
<key>textureRotated</key>
<true/>
<false/>
</dict>
<key>Walking_10.png</key>
<dict>
@@ -1260,7 +1305,7 @@
<key>spriteSourceSize</key>
<string>{81,97}</string>
<key>textureRect</key>
<string>{{760,306},{81,97}}</string>
<string>{{300,402},{81,97}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1275,7 +1320,7 @@
<key>spriteSourceSize</key>
<string>{81,97}</string>
<key>textureRect</key>
<string>{{780,201},{81,97}}</string>
<string>{{821,0},{81,97}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1290,7 +1335,7 @@
<key>spriteSourceSize</key>
<string>{81,97}</string>
<key>textureRect</key>
<string>{{786,99},{81,97}}</string>
<string>{{793,200},{81,97}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1305,7 +1350,7 @@
<key>spriteSourceSize</key>
<string>{81,97}</string>
<key>textureRect</key>
<string>{{825,0},{81,97}}</string>
<string>{{859,97},{81,97}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1320,7 +1365,7 @@
<key>spriteSourceSize</key>
<string>{81,97}</string>
<key>textureRect</key>
<string>{{841,298},{81,97}}</string>
<string>{{902,0},{81,97}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1335,7 +1380,7 @@
<key>spriteSourceSize</key>
<string>{81,97}</string>
<key>textureRect</key>
<string>{{848,395},{81,97}}</string>
<string>{{800,297},{81,97}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1350,7 +1395,7 @@
<key>spriteSourceSize</key>
<string>{81,97}</string>
<key>textureRect</key>
<string>{{861,196},{81,97}}</string>
<string>{{874,194},{81,97}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1365,7 +1410,7 @@
<key>spriteSourceSize</key>
<string>{81,97}</string>
<key>textureRect</key>
<string>{{867,97},{81,97}}</string>
<string>{{940,97},{81,97}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1380,7 +1425,7 @@
<key>spriteSourceSize</key>
<string>{81,97}</string>
<key>textureRect</key>
<string>{{906,0},{81,97}}</string>
<string>{{983,0},{81,97}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1395,7 +1440,7 @@
<key>spriteSourceSize</key>
<string>{81,97}</string>
<key>textureRect</key>
<string>{{922,293},{81,97}}</string>
<string>{{821,394},{81,97}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1410,7 +1455,7 @@
<key>spriteSourceSize</key>
<string>{81,97}</string>
<key>textureRect</key>
<string>{{942,194},{81,97}}</string>
<string>{{881,291},{81,97}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1425,7 +1470,7 @@
<key>spriteSourceSize</key>
<string>{81,97}</string>
<key>textureRect</key>
<string>{{948,97},{81,97}}</string>
<string>{{955,194},{81,97}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1440,7 +1485,7 @@
<key>spriteSourceSize</key>
<string>{81,97}</string>
<key>textureRect</key>
<string>{{987,0},{81,97}}</string>
<string>{{1021,97},{81,97}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1455,7 +1500,7 @@
<key>spriteSourceSize</key>
<string>{81,97}</string>
<key>textureRect</key>
<string>{{929,390},{81,97}}</string>
<string>{{1064,0},{81,97}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1470,7 +1515,7 @@
<key>spriteSourceSize</key>
<string>{81,97}</string>
<key>textureRect</key>
<string>{{1003,291},{81,97}}</string>
<string>{{902,388},{81,97}}</string>
<key>textureRotated</key>
<false/>
</dict>
@@ -1486,9 +1531,9 @@
<key>realTextureFileName</key>
<string>MonkGirl.png</string>
<key>size</key>
<string>{1505,496}</string>
<string>{1549,500}</string>
<key>smartupdate</key>
<string>$TexturePacker:SmartUpdate:8383576ddc6ed0fb9e6adcbc98ec9c07:b0caf27c9f592741053365a3d87b3473:7b088363a1f16e4f4ff313aecc52227b$</string>
<string>$TexturePacker:SmartUpdate:f2fd96a7a4bba5a2e1c4622dcb63e1f2:17c698372c46bf0be82704dd808cd6f4:7b088363a1f16e4f4ff313aecc52227b$</string>
<key>textureFileName</key>
<string>MonkGirl.png</string>
</dict>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 98 KiB

View File

@@ -0,0 +1,43 @@
{
"__type__": "cc.AnimationClip",
"_name": "TurnAround1",
"_objFlags": 0,
"_native": "",
"_duration": 0.15,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "c1a00209-f74d-41b5-a5da-df5720ac34b4"
}
},
{
"frame": 0.03333333333333333,
"value": {
"__uuid__": "2b52c0f1-2360-4a2b-9233-bf5662de09a5"
}
},
{
"frame": 0.08333333333333333,
"value": {
"__uuid__": "e3f9dfe7-ed91-4dc3-b68b-a3a3c2637074"
}
},
{
"frame": 0.13333333333333333,
"value": {
"__uuid__": "7515ef50-3a14-4e58-8811-a0c890fc40f3"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,5 @@
{
"ver": "2.1.0",
"uuid": "6e1139d4-03dd-4bd4-9510-606e94f629fe",
"subMetas": {}
}

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.2" tiledversion="1.2.3" orientation="orthogonal" renderorder="right-down" width="128" height="128" tilewidth="16" tileheight="16" infinite="0" nextlayerid="6" nextobjectid="113">
<map version="1.2" tiledversion="1.2.3" orientation="orthogonal" renderorder="right-down" width="128" height="64" tilewidth="16" tileheight="16" infinite="0" nextlayerid="7" nextobjectid="137">
<tileset firstgid="1" source="tiles0.tsx"/>
<tileset firstgid="65" source="tiles1.tsx"/>
<tileset firstgid="129" source="tiles2.tsx"/>
<layer id="2" name="Ground" width="128" height="128">
<layer id="6" name="Ground" width="128" height="64">
<data encoding="base64" compression="zlib">
eJzt3LFu00AcwOEoFUuHigqBBANTByRegrlTWWBj6gsgWGBCqngAFgZ23hNHsiXj5mLncs6dfd/wSVUbWa1/f199VpSLzWZzAQAAAAAAAAAAAAAAAAAAES5buX8Pzue+p+t/X6HcHXL237a6/p8atwHbFdL///4h+q9Pv//tSP/LAlrpP1//ffRft93f/ry179wM14TcrfQ/b/8a6K9/7g45+z+LkLuZ/nn7r2kG9Nc/d4cl9i+J/nX2d/3X3T/FDOi/XK5//fWvt3+KGdA//bntnik+nGjua19//fVfRv+XLf3r6d/v3f9af/31z9f/6YiU/fv0z9t/rPu+/r8bH47U9Xf/V07/qe3vNu7/l2Jq/6ntt/ovylj/fY3fNq4C7Yf9h+6OpH++/vvaX/UMu8/R/0XjRv9i+h9a9/v9U9O/3P4x94jH0v/8/afMwPBcpuw7JmX/bQEtSuyf6hwfEtNe//X0P2ZG5ji2/qfPwN9ELVIdR/90/afMgP7LpL/+JXXL1T93B/31X3L/Xwnpv7z+S6Z/3fSvm/51079u+tdN/7rpXzf966Z/3fSvm/51079u+pfrJkD/MvrP9X7RUPc55kD/cvpfj3gSoP86+uegf3xv/Zet9Ps//dfXP/S/vfv5+4T6xwytT97/Pe5ja7jed9/PfQ2fev3rf9ih//nD/q8LaBqyb43QP2zXMrTn2hnbr12PHD93+65/7g6l9u86vznBqfvzOdvr/3i9Tr1+p3hGM1d7/dM/Twv1zzEDU/YItfefu8Fwts71nGjqHlH/8/bvZmDOz3s55hmB/o+lvJ8/tH8I+REhpr3+4/1OnYOY/jEz8DOS/tPEzsGrTVz/3WcBfA207nxvfG5fq/+8/WM1/d/F9t/5sgn3/9Z73a7ln5b+0/uTvwMAAAAAAAAAAAAAAABwfv8AQJoGWw==
eJzt201uwjAQhuEIxCY7KugeqTepumHXC/T+xyCqYimy4sQ4E2bE9y6eDf+e1w4bOHZddwQAAAAAAAAAAACAF/jBP+8Onv29P4M35Rkor50ZaK+dGWivnRlor50ZtK39UmnL5/owegz94/X/on8Ykfsv9V27n/72a0/drPqfBucZeeMSjxm8m5b+W1m9Dv3fv//c9eG88f3p397fytr1vNR9j31A/1hq21vtg4gziNz/ZvQY+vubrr0fefdv3QOt+0O9/3cm3ZffntwqlZ4fTZqBdwuv/odROv9/g3vBwUDpjFq8dst7q5//vP/0O2B6m1V/T/Qv979nvedY9/jcwTPXHPov9+lXZldjrb/1fqL/c/2vo6W5bTn/S3tg7/Nfsz/pX+5v+Z1L/3i8f3cdhXcHz/6/4uivjf7a6K+N/tror43+2uivjf7a6K+N/tror43+2uivjf7a6K+N/tror43+2uivjf7a6K+N/trSf6C8W9Cf/vSn/6v7Y7/+Dyz1uAA=
</data>
</layer>
<objectgroup id="1" name="PlayerStartingPos">
<object id="135" x="1040.33" y="1081">
<object id="135" x="1400" y="580">
<point/>
</object>
<object id="137" x="1134.67" y="1081.67">
<object id="137" x="1500" y="580">
<point/>
</object>
</objectgroup>
<objectgroup id="4" name="NpcStartingPos">
<object id="108" x="926" y="1447">
<object id="108" x="927.333" y="535">
<properties>
<property name="dirX" value="-2"/>
<property name="speciesId" value="4196"/>
@@ -26,28 +26,28 @@
</object>
</objectgroup>
<objectgroup id="5" name="NpcPatrolCue">
<object id="109" x="773.337" y="1468.67">
<object id="109" x="774.67" y="556.67">
<properties>
<property name="flAct" value="36"/>
<property name="frAct" value="35"/>
</properties>
<point/>
</object>
<object id="110" x="728" y="1500">
<object id="110" x="729.333" y="588">
<properties>
<property name="flAct" value="4"/>
<property name="frAct" value="35"/>
</properties>
<point/>
</object>
<object id="111" x="668" y="1500">
<object id="111" x="669.333" y="588">
<properties>
<property name="flAct" value="3"/>
<property name="frAct" value="3"/>
</properties>
<point/>
</object>
<object id="112" x="984" y="1447">
<object id="112" x="985.333" y="535">
<properties>
<property name="flAct" value="4"/>
<property name="frAct" value="4"/>
@@ -59,197 +59,112 @@
<properties>
<property name="type" value="barrier_and_shelter"/>
</properties>
<object id="54" x="656" y="1504" width="80" height="16">
<object id="57" x="768" y="560" width="32" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="55" x="736" y="1552" width="112" height="16">
<object id="60" x="1232" y="448" width="208" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="57" x="768" y="1472" width="32" height="16">
<object id="65" x="1040" y="576" width="32" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="58" x="1040" y="1536" width="80" height="16">
<object id="66" x="1040" y="560" width="16" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="59" x="1040" y="1568" width="224" height="48">
<object id="67" x="784" y="544" width="256" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="60" x="1216" y="1344" width="224" height="16">
<object id="84" x="640" y="224" width="16" height="800">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="62" x="1040" y="1552" width="208" height="16">
<object id="85" x="1680" y="224" width="16" height="800">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="63" x="1040" y="1504" width="48" height="16">
<object id="86" x="1104" y="496" width="96" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="64" x="1040" y="1520" width="64" height="16">
<object id="90" x="1248" y="464" width="320" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="65" x="1040" y="1488" width="32" height="16">
<object id="97" x="1248" y="416" width="158" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="66" x="1040" y="1472" width="16" height="16">
<object id="98" x="1280" y="400" width="96" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="67" x="784" y="1456" width="256" height="16">
<object id="100" x="1538" y="560" width="144" height="32">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="73" x="784" y="1568" width="96" height="16">
<object id="101" x="1568" y="528" width="112" height="32">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="74" x="816" y="1584" width="96" height="16">
<object id="102" x="1136" y="368" width="96" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="79" x="640" y="1616" width="1056" height="16">
<object id="103" x="1600" y="496" width="80" height="32">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="83" x="640" y="480" width="1056" height="16">
<object id="104" x="816" y="414" width="304" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="84" x="640" y="480" width="16" height="1152">
<object id="105" x="816" y="366" width="16" height="64">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="85" x="1680" y="480" width="16" height="1152">
<object id="106" x="1104" y="334" width="16" height="96">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="86" x="1104" y="1408" width="96" height="16">
<object id="113" x="640" y="1008" width="1056" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="87" x="1456" y="1568" width="224" height="48">
<object id="114" x="640" y="224" width="1056" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="88" x="1264" y="1584" width="16" height="32">
<object id="119" x="656" y="592" width="1024" height="416">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="89" x="1280" y="1600" width="16" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="90" x="1232" y="1408" width="304" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="91" x="1440" y="1584" width="16" height="32">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="92" x="1424" y="1600" width="16" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="93" x="1488" y="1552" width="192" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="94" x="1504" y="1536" width="176" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="95" x="1520" y="1520" width="160" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="96" x="1568" y="1408" width="16" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="97" x="1248" y="1328" width="158" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="98" x="1280" y="1312" width="96" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="99" x="1536" y="1504" width="144" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="100" x="1552" y="1488" width="128" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="101" x="1568" y="1472" width="112" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="102" x="1584" y="1456" width="96" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="103" x="1600" y="1440" width="80" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="104" x="928" y="1088" width="304" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="105" x="928" y="1008" width="16" height="96">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="106" x="1216" y="1008" width="16" height="96">
<object id="136" x="1232" y="432" width="208" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>

View File

@@ -6,12 +6,12 @@ import "geometry.proto"; // The import path here is only w.r.t. the proto file,
message PlayerDownsync {
int32 id = 1;
int32 virtualGridX = 2;
int32 virtualGridY = 3;
int32 virtualGridX = 2;
int32 virtualGridY = 3;
int32 dirX = 4;
int32 dirY = 5; // "dirX" and "dirY" determines character facing
int32 velX = 6;
int32 velY = 7; // "velX" and "velY" is used to record the accumulated effect by accelerations (including gravity)
int32 dirY = 5;
int32 velX = 6;
int32 velY = 7; // "velX" and "velY" is used to record the accumulated effect by inertia and accelerations (including gravity)
int32 speed = 8; // this is the instantaneous scalar attribute of a character, different from but will be accounted in "velX" and "velY"
int32 battleState = 9;
int32 joinIndex = 10;
@@ -32,6 +32,12 @@ message PlayerDownsync {
int32 bulletTeamId = 24;
int32 chCollisionTeamId = 25;
bool onWall = 26; // like "inAir", its by design a standalone field only inferred by the collision result of "applyInputFrameDownsyncDynamicsOnSingleRenderFrame" instead of "characterState", because we need check the transition for "characterState" from this field, i.e. "onWall (prev -> curr)"
int32 onWallNormX = 27;
int32 onWallNormY = 28;
bool capturedByInertia = 29; // like "inAir", its by design a standalone field only inferred by the calc result of "applyInputFrameDownsyncDynamicsOnSingleRenderFrame" instead of "characterState"
string name = 997;
string displayName = 998;
string avatar = 999;
@@ -47,6 +53,7 @@ message InputFrameDecoded {
message InputFrameUpsync {
int32 inputFrameId = 1;
uint64 encoded = 2;
int32 joinIndex = 3;
}
message InputFrameDownsync {
@@ -56,96 +63,108 @@ message InputFrameDownsync {
}
message HeartbeatUpsync {
int64 clientTimestamp = 1;
int64 clientTimestamp = 1;
}
message WsReq {
int32 msgId = 1;
int32 playerId = 2;
int32 act = 3;
int32 act = 3;
int32 joinIndex = 4;
int32 ackingFrameId = 5;
int32 ackingInputFrameId = 6;
repeated InputFrameUpsync inputFrameUpsyncBatch = 7;
HeartbeatUpsync hb = 8;
repeated InputFrameUpsync inputFrameUpsyncBatch = 7;
HeartbeatUpsync hb = 8;
}
message WsResp {
int32 ret = 1;
int32 echoedMsgId = 2;
int32 act = 3;
RoomDownsyncFrame rdf = 4;
int32 echoedMsgId = 2;
int32 act = 3;
RoomDownsyncFrame rdf = 4;
repeated InputFrameDownsync inputFrameDownsyncBatch = 5;
BattleColliderInfo bciFrame = 6;
BattleColliderInfo bciFrame = 6;
int32 peerJoinIndex = 7; // Only used when "InputsBufferSnapshot.peerJoinIndex" is used.
}
message InputsBufferSnapshot {
int32 refRenderFrameId = 1;
int32 refRenderFrameId = 1;
uint64 unconfirmedMask = 2;
repeated InputFrameDownsync toSendInputFrameDownsyncs = 3;
bool shouldForceResync = 4;
int32 peerJoinIndex = 5; // Only used when "WsResp.peerJoinIndex" is used.
}
message MeleeBullet {
message MeleeBullet {
// Jargon reference https://www.thegamer.com/fighting-games-frame-data-explained/
// ALL lengths are in world coordinate
// for offender
int32 originatedRenderFrameId = 1;
int32 offenderJoinIndex = 2;
int32 originatedRenderFrameId = 1;
int32 offenderJoinIndex = 2;
int32 startupFrames = 3;
int32 startupFrames = 3;
int32 cancellableStFrame = 4;
int32 cancellableEdFrame = 5;
int32 activeFrames = 6;
int32 activeFrames = 6;
int32 hitStunFrames = 7;
int32 blockStunFrames = 8;
int32 pushbackVelX = 9;
int32 pushbackVelY = 10;
int32 damage = 11;
int32 hitStunFrames = 7;
int32 blockStunFrames = 8;
int32 pushbackVelX = 9;
int32 pushbackVelY = 10;
int32 damage = 11;
int32 selfLockVelX = 12;
int32 selfLockVelY = 13;
int32 selfLockVelX = 12;
int32 selfLockVelY = 13;
int32 hitboxOffsetX = 14;
int32 hitboxOffsetY = 15;
int32 hitboxSizeX = 16;
int32 hitboxOffsetX = 14;
int32 hitboxOffsetY = 15;
int32 hitboxSizeX = 16;
int32 hitboxSizeY = 17;
bool blowUp = 18;
int32 teamId = 19;
int32 bulletLocalId = 20;
}
int32 bulletLocalId = 20;
int32 speciesId = 21;
int32 explosionFrames = 22;
message FireballBullet {
int32 originatedRenderFrameId = 1;
int32 offenderJoinIndex = 2;
int32 blState = 23;
int32 framesInBlState = 24;
}
int32 startupFrames = 3;
message FireballBullet {
int32 originatedRenderFrameId = 1;
int32 offenderJoinIndex = 2;
int32 startupFrames = 3;
int32 cancellableStFrame = 4;
int32 cancellableEdFrame = 5;
int32 activeFrames = 6;
int32 activeFrames = 6;
int32 hitStunFrames = 7;
int32 blockStunFrames = 8;
int32 pushbackVelX = 9;
int32 pushbackVelY = 10;
int32 damage = 11;
int32 hitStunFrames = 7;
int32 blockStunFrames = 8;
int32 pushbackVelX = 9;
int32 pushbackVelY = 10;
int32 damage = 11;
int32 selfLockVelX = 12;
int32 selfLockVelY = 13;
int32 selfLockVelX = 12;
int32 selfLockVelY = 13;
int32 hitboxOffsetX = 14;
int32 hitboxOffsetY = 15;
int32 hitboxSizeX = 16;
int32 hitboxOffsetX = 14;
int32 hitboxOffsetY = 15;
int32 hitboxSizeX = 16;
int32 hitboxSizeY = 17;
bool blowUp = 18;
int32 teamId = 19;
int32 bulletLocalId = 20;
int32 bulletLocalId = 20;
int32 speciesId = 21;
int32 explosionFrames = 22;
int32 blState = 23;
int32 framesInBlState = 24;
int32 virtualGridX = 999;
int32 virtualGridY = 1000;
@@ -154,20 +173,20 @@ message FireballBullet {
int32 velX = 1003;
int32 velY = 1004;
int32 speed = 1005;
}
}
message BattleColliderInfo {
string stageName = 1;
int32 intervalToPing = 2;
int32 intervalToPing = 2;
int32 willKickIfInactiveFor = 3;
int32 boundRoomId = 4;
int64 battleDurationNanos = 5;
int32 inputFrameUpsyncDelayTolerance = 6;
int32 boundRoomId = 4;
int64 battleDurationNanos = 5;
int32 inputFrameUpsyncDelayTolerance = 6;
int32 maxChasingRenderFramesPerUpdate = 7;
double rollbackEstimatedDtMillis = 8;
int64 rollbackEstimatedDtNanos = 9;
int32 renderCacheSize = 10;
double spaceOffsetX = 11;
double spaceOffsetY = 12;
@@ -181,7 +200,7 @@ message RoomDownsyncFrame {
repeated PlayerDownsync playersArr = 2;
int64 countdownNanos = 3;
repeated MeleeBullet meleeBullets = 4; // I don't know how to mimic inheritance/composition in protobuf by far, thus using an array for each type of bullet as a compromise
repeated FireballBullet fireballBullets = 5;
repeated FireballBullet fireballBullets = 5;
uint64 backendUnconfirmedMask = 1024; // Indexed by "joinIndex", same compression concern as stated in InputFrameDownsync
bool shouldForceResync = 1025;

View File

@@ -31,13 +31,10 @@
"_components": [
{
"__id__": 22
},
{
"__id__": 23
}
],
"_prefab": {
"__id__": 24
"__id__": 23
},
"_opacity": 255,
"_color": {
@@ -485,6 +482,13 @@
},
{
"__uuid__": "e8247e2a-1b5b-4618-86f8-224b25246b55"
},
null,
null,
null,
null,
{
"__uuid__": "6e1139d4-03dd-4bd4-9510-606e94f629fe"
}
],
"playOnLoad": false,
@@ -648,6 +652,17 @@
},
{
"__uuid__": "9b500cb0-8048-4715-81db-cc975c914225"
},
null,
null,
{
"__uuid__": "38b2c892-347b-4009-93f8-65b2ab1614f0"
},
{
"__uuid__": "411f964a-4dd8-424c-b2e2-d92b10474ce2"
},
{
"__uuid__": "e906322d-a08b-4477-a2e9-98acd42fa034"
}
],
"playOnLoad": false,
@@ -814,6 +829,14 @@
},
{
"__uuid__": "7e0a1e98-ee5a-446f-bec2-7d72b6916503"
},
{
"__uuid__": "0abbd156-980e-475e-9994-3c958bd913fc"
},
null,
null,
{
"__uuid__": "edd23b2f-1caa-4836-88a7-e4af1f26743e"
}
],
"playOnLoad": false,
@@ -869,32 +892,6 @@
"fileId": "7aN7Gcc/tBw5EGlTJVBj2+",
"sync": false
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 1
},
"_enabled": true,
"_materials": [],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": null,
"_type": 0,
"_sizeMode": 0,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_atlas": null,
"_id": ""
},
{
"__type__": "b74b05YDqZFRo4OkZRFZX8k",
"_name": "",

View File

@@ -8,7 +8,8 @@
"__id__": 1
},
"optimizationPolicy": 0,
"asyncLoadAssets": false
"asyncLoadAssets": false,
"readonly": false
},
{
"__type__": "cc.Node",
@@ -27,20 +28,19 @@
},
{
"__id__": 11
},
{
"__id__": 14
}
],
"_active": true,
"_level": 1,
"_components": [
{
"__id__": 14
},
{
"__id__": 15
"__id__": 17
}
],
"_prefab": {
"__id__": 16
"__id__": 18
},
"_opacity": 255,
"_color": {
@@ -52,25 +52,14 @@
},
"_contentSize": {
"__type__": "cc.Size",
"width": 1024,
"height": 1920
"width": 960,
"height": 640
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_quat": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_skewX": 0,
"_skewY": 0,
"groupIndex": 0,
"_id": "",
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
@@ -86,18 +75,29 @@
1,
1
]
}
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Node",
"_name": "WhiteStars",
"_name": "Background",
"_objFlags": 0,
"_parent": {
"__id__": 1
},
"_children": [],
"_active": true,
"_level": 2,
"_components": [
{
"__id__": 3
@@ -109,37 +109,26 @@
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"r": 0,
"g": 163,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 268,
"height": 112
"width": 1920,
"height": 1280
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_quat": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_skewX": 0,
"_skewY": 0,
"groupIndex": 0,
"_id": "",
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
-16,
0,
0,
0,
0,
@@ -150,7 +139,19 @@
1,
1
]
}
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Sprite",
@@ -160,11 +161,18 @@
"__id__": 2
},
"_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": {
"__uuid__": "1a2d934e-9d6d-45bf-83c6-564586cc8400"
"__uuid__": "637f31c2-c53e-4dec-ae11-d56c0c6177ad"
},
"_type": 0,
"_sizeMode": 1,
"_sizeMode": 0,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
@@ -174,12 +182,9 @@
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_state": 0,
"_atlas": {
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
},
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_id": ""
},
{
@@ -190,7 +195,7 @@
"asset": {
"__uuid__": "230eeb1f-e0f9-4a41-ab6c-05b3771cbf3e"
},
"fileId": "50Mjaee6xFXLrZ/mSBD3P5",
"fileId": "83iQr+5XNNF5E2qjV+WUp0",
"sync": false
},
{
@@ -202,7 +207,6 @@
},
"_children": [],
"_active": true,
"_level": 3,
"_components": [
{
"__id__": 6
@@ -229,17 +233,6 @@
"x": 0.5,
"y": 0.5
},
"_quat": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_skewX": 0,
"_skewY": 0,
"groupIndex": 0,
"_id": "",
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
@@ -255,7 +248,19 @@
1,
1
]
}
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Sprite",
@@ -265,6 +270,13 @@
"__id__": 5
},
"_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": {
"__uuid__": "75a2c1e3-2c22-480c-9572-eb65f4a554e1"
},
@@ -279,12 +291,9 @@
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_state": 0,
"_atlas": {
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
},
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_id": ""
},
{
@@ -307,7 +316,6 @@
},
"_children": [],
"_active": true,
"_level": 2,
"_components": [
{
"__id__": 9
@@ -327,24 +335,13 @@
"_contentSize": {
"__type__": "cc.Size",
"width": 111.23,
"height": 200
"height": 252
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_quat": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_skewX": 0,
"_skewY": 0,
"groupIndex": 0,
"_id": "",
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
@@ -360,7 +357,19 @@
0.66667,
0.66667
]
}
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Label",
@@ -370,6 +379,11 @@
"__id__": 8
},
"_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_useOriginalSize": false,
"_string": "3",
"_N$string": "3",
@@ -407,7 +421,6 @@
},
"_children": [],
"_active": true,
"_level": 2,
"_components": [
{
"__id__": 12
@@ -434,17 +447,6 @@
"x": 0.5,
"y": 0.5
},
"_quat": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_skewX": 0,
"_skewY": 0,
"groupIndex": 0,
"_id": "",
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
@@ -460,7 +462,19 @@
1,
1
]
}
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Sprite",
@@ -470,6 +484,13 @@
"__id__": 11
},
"_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": {
"__uuid__": "637f31c2-c53e-4dec-ae11-d56c0c6177ad"
},
@@ -484,12 +505,9 @@
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_state": 0,
"_atlas": {
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
},
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_id": ""
},
{
@@ -503,6 +521,115 @@
"fileId": "21dxpL7zlKIIDhUt+GIMbg",
"sync": false
},
{
"__type__": "cc.Node",
"_name": "WhiteStars",
"_objFlags": 0,
"_parent": {
"__id__": 1
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 15
}
],
"_prefab": {
"__id__": 16
},
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 268,
"height": 112
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
-16,
0,
0,
0,
0,
0,
1,
1,
1,
1
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 14
},
"_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": {
"__uuid__": "1a2d934e-9d6d-45bf-83c6-564586cc8400"
},
"_type": 0,
"_sizeMode": 1,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_atlas": {
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
},
"_id": ""
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__uuid__": "230eeb1f-e0f9-4a41-ab6c-05b3771cbf3e"
},
"fileId": "50Mjaee6xFXLrZ/mSBD3P5",
"sync": false
},
{
"__type__": "6a3d6Y6Ki1BiqAVSKIRdwRl",
"_name": "",
@@ -516,34 +643,6 @@
},
"_id": ""
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 1
},
"_enabled": true,
"_spriteFrame": {
"__uuid__": "334d4f93-b007-49e8-9268-35891d4f4ebb"
},
"_type": 0,
"_sizeMode": 1,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_state": 0,
"_atlas": null,
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_id": ""
},
{
"__type__": "cc.PrefabInfo",
"root": {

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"ver": "1.2.5",
"uuid": "3ed4c7bc-79d0-4075-a563-d5a58ae798f9",
"uuid": "dc804c5c-ff76-445e-ac69-52269055c3c5",
"optimizationPolicy": "AUTO",
"asyncLoadAssets": false,
"readonly": false,

View File

@@ -0,0 +1,443 @@
[
{
"__type__": "cc.Prefab",
"_name": "",
"_objFlags": 0,
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"asyncLoadAssets": false,
"readonly": false
},
{
"__type__": "cc.Node",
"_name": "Root",
"_objFlags": 0,
"_parent": null,
"_children": [
{
"__id__": 2
}
],
"_active": true,
"_components": [
{
"__id__": 12
}
],
"_prefab": {
"__id__": 13
},
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 120,
"height": 120
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
0,
0,
0,
0,
0,
0,
1,
1,
1,
1
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 2,
"groupIndex": 2,
"_id": ""
},
{
"__type__": "cc.Node",
"_name": "animNode",
"_objFlags": 0,
"_parent": {
"__id__": 1
},
"_children": [
{
"__id__": 3
},
{
"__id__": 7
}
],
"_active": true,
"_components": [],
"_prefab": {
"__id__": 11
},
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 0,
"height": 0
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
0,
0,
0,
0,
0,
0,
1,
1,
1,
1
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Node",
"_name": "Fireball1",
"_objFlags": 0,
"_parent": {
"__id__": 2
},
"_children": [],
"_active": false,
"_components": [
{
"__id__": 4
},
{
"__id__": 5
}
],
"_prefab": {
"__id__": 6
},
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 117,
"height": 55
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
-32,
0,
0,
0,
0,
0,
1,
1,
1,
1
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 3
},
"_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": null,
"_type": 0,
"_sizeMode": 1,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_atlas": {
"__uuid__": "6dcd5722-8ef9-47fd-9520-861d2713e274"
},
"_id": ""
},
{
"__type__": "cc.Animation",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 3
},
"_enabled": true,
"_defaultClip": {
"__uuid__": "ba12416b-eec3-4260-8402-7fc25b125624"
},
"_clips": [
{
"__uuid__": "ba12416b-eec3-4260-8402-7fc25b125624"
},
{
"__uuid__": "7941215a-2b8c-4798-954b-4f1b16d5f6f5"
}
],
"playOnLoad": false,
"_id": ""
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__uuid__": "d92d4831-cd65-4eb5-90bd-b77021aec35b"
},
"fileId": "5f1s6pDt5F3rknJTu0gQW7",
"sync": false
},
{
"__type__": "cc.Node",
"_name": "MeleeExplosion",
"_objFlags": 0,
"_parent": {
"__id__": 2
},
"_children": [],
"_active": false,
"_components": [
{
"__id__": 8
},
{
"__id__": 9
}
],
"_prefab": {
"__id__": 10
},
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 0,
"height": 0
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
24,
8,
0,
0,
0,
0,
1,
1,
1,
1
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Animation",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 7
},
"_enabled": true,
"_defaultClip": null,
"_clips": [
{
"__uuid__": "954a2924-89df-4df4-93fc-36d2b22e7619"
},
{
"__uuid__": "5bd304eb-c8ba-426f-a9ab-5698ac62de85"
},
{
"__uuid__": "5054633c-a588-4506-b4ac-eef29b1d8511"
}
],
"playOnLoad": false,
"_id": ""
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 7
},
"_enabled": true,
"_materials": [],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": null,
"_type": 0,
"_sizeMode": 1,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_atlas": {
"__uuid__": "1c4c1dcb-54af-485b-9119-abd6d6d84526"
},
"_id": ""
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__uuid__": "d92d4831-cd65-4eb5-90bd-b77021aec35b"
},
"fileId": "fd9jQiClRJSI00917fifB8",
"sync": false
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__uuid__": "d92d4831-cd65-4eb5-90bd-b77021aec35b"
},
"fileId": "3824oBeVVL1KOAQ6Zd9CC5",
"sync": false
},
{
"__type__": "e66a2qRmRZGnqSyVMwLy6Pw",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 1
},
"_enabled": true,
"animNode": {
"__id__": 2
},
"_id": ""
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__uuid__": "d92d4831-cd65-4eb5-90bd-b77021aec35b"
},
"fileId": "4cx75uwJJFa7U8QL187QCL",
"sync": false
}
]

View File

@@ -0,0 +1,8 @@
{
"ver": "1.2.5",
"uuid": "d92d4831-cd65-4eb5-90bd-b77021aec35b",
"optimizationPolicy": "AUTO",
"asyncLoadAssets": false,
"readonly": false,
"subMetas": {}
}

View File

@@ -21,20 +21,20 @@
"__id__": 2
},
{
"__id__": 10
"__id__": 5
}
],
"_active": true,
"_components": [
{
"__id__": 13
"__id__": 12
},
{
"__id__": 14
"__id__": 13
}
],
"_prefab": {
"__id__": 15
"__id__": 14
},
"_opacity": 255,
"_color": {
@@ -46,8 +46,72 @@
},
"_contentSize": {
"__type__": "cc.Size",
"width": 1024,
"height": 1920
"width": 960,
"height": 640
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
480,
320,
0,
0,
0,
0,
1,
1,
1,
1
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Node",
"_name": "Background",
"_objFlags": 0,
"_parent": {
"__id__": 1
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 3
}
],
"_prefab": {
"__id__": 4
},
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 1920,
"height": 1280
},
"_anchorPoint": {
"__type__": "cc.Vec2",
@@ -83,6 +147,51 @@
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 2
},
"_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": {
"__uuid__": "637f31c2-c53e-4dec-ae11-d56c0c6177ad"
},
"_type": 0,
"_sizeMode": 0,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_atlas": {
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
},
"_id": ""
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__uuid__": "32b8e752-8362-4783-a4a6-1160af8b7109"
},
"fileId": "a7oR1cZvVO/pp9QJgLnJyt",
"sync": false
},
{
"__type__": "cc.Node",
"_name": "modeButton",
@@ -92,20 +201,20 @@
},
"_children": [
{
"__id__": 3
"__id__": 6
}
],
"_active": true,
"_components": [
{
"__id__": 7
"__id__": 9
},
{
"__id__": 8
"__id__": 10
}
],
"_prefab": {
"__id__": 9
"__id__": 11
},
"_opacity": 255,
"_color": {
@@ -117,8 +226,8 @@
},
"_contentSize": {
"__type__": "cc.Size",
"width": 280,
"height": 130
"width": 240,
"height": 100
},
"_anchorPoint": {
"__type__": "cc.Vec2",
@@ -130,7 +239,7 @@
"ctor": "Float64Array",
"array": [
0,
-564,
-90.495,
0,
0,
0,
@@ -159,20 +268,17 @@
"_name": "Label",
"_objFlags": 0,
"_parent": {
"__id__": 2
"__id__": 5
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 4
},
{
"__id__": 5
"__id__": 7
}
],
"_prefab": {
"__id__": 6
"__id__": 8
},
"_opacity": 255,
"_color": {
@@ -226,7 +332,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 3
"__id__": 6
},
"_enabled": true,
"_materials": [
@@ -235,8 +341,8 @@
}
],
"_useOriginalSize": false,
"_string": "gameRule.mode",
"_N$string": "gameRule.mode",
"_string": "1 v 1",
"_N$string": "1 v 1",
"_fontSize": 55,
"_lineHeight": 50,
"_enableWrapText": false,
@@ -251,17 +357,6 @@
"_N$cacheMode": 0,
"_id": ""
},
{
"__type__": "744dcs4DCdNprNhG0xwq6FK",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 3
},
"_enabled": true,
"_dataID": "gameRule.mode",
"_id": ""
},
{
"__type__": "cc.PrefabInfo",
"root": {
@@ -278,7 +373,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 2
"__id__": 5
},
"_enabled": true,
"_materials": [
@@ -312,7 +407,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 2
"__id__": 5
},
"_enabled": true,
"_normalMaterial": null,
@@ -375,7 +470,7 @@
"hoverSprite": null,
"_N$disabledSprite": null,
"_N$target": {
"__id__": 2
"__id__": 5
},
"_id": ""
},
@@ -390,115 +485,6 @@
"fileId": "c54lqSflFD8ogSYAhsAkKh",
"sync": false
},
{
"__type__": "cc.Node",
"_name": "decoration",
"_objFlags": 0,
"_parent": {
"__id__": 1
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 11
}
],
"_prefab": {
"__id__": 12
},
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 543,
"height": 117
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
0,
-312,
0,
0,
0,
0,
1,
1,
1,
1
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 10
},
"_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": {
"__uuid__": "153d890a-fc37-4d59-8779-93a8fb19fa85"
},
"_type": 0,
"_sizeMode": 1,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_atlas": {
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
},
"_id": ""
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__uuid__": "32b8e752-8362-4783-a4a6-1160af8b7109"
},
"fileId": "1bbMLAzntHZpEudL8lM/Lx",
"sync": false
},
{
"__type__": "dd92bKVy8FJY7uq3ieoNZCZ",
"_name": "",
@@ -508,41 +494,36 @@
},
"_enabled": true,
"modeButton": {
"__id__": 8
"__id__": 10
},
"mapNode": null,
"_id": ""
},
{
"__type__": "cc.Sprite",
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 1
},
"_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": {
"__uuid__": "7838f276-ab48-445a-b858-937dd27d9520"
},
"_type": 0,
"_sizeMode": 0,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_atlas": null,
"alignMode": 1,
"_target": null,
"_alignFlags": 18,
"_left": 0,
"_right": 0,
"_top": 0,
"_bottom": 0,
"_verticalCenter": 0,
"_horizontalCenter": 0,
"_isAbsLeft": true,
"_isAbsRight": true,
"_isAbsTop": true,
"_isAbsBottom": true,
"_isAbsHorizontalCenter": true,
"_isAbsVerticalCenter": true,
"_originalWidth": 0,
"_originalHeight": 0,
"_id": ""
},
{

View File

@@ -8,7 +8,8 @@
"__id__": 1
},
"optimizationPolicy": 0,
"asyncLoadAssets": false
"asyncLoadAssets": false,
"readonly": false
},
{
"__type__": "cc.Node",
@@ -20,18 +21,17 @@
"__id__": 2
},
{
"__id__": 6
"__id__": 5
}
],
"_active": true,
"_level": 1,
"_components": [
{
"__id__": 9
"__id__": 8
}
],
"_prefab": {
"__id__": 10
"__id__": 9
},
"_opacity": 255,
"_color": {
@@ -51,24 +51,12 @@
"x": 0.5,
"y": 0.5
},
"_quat": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_skewX": 0,
"_skewY": 0,
"_zIndex": 0,
"groupIndex": 0,
"_id": "",
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
512,
0,
480,
480,
0,
0,
0,
@@ -78,7 +66,19 @@
1,
1
]
}
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Node",
@@ -89,17 +89,13 @@
},
"_children": [],
"_active": true,
"_level": 0,
"_components": [
{
"__id__": 3
},
{
"__id__": 4
}
],
"_prefab": {
"__id__": 5
"__id__": 4
},
"_opacity": 255,
"_color": {
@@ -111,32 +107,20 @@
},
"_contentSize": {
"__type__": "cc.Size",
"width": 303.5,
"height": 30
"width": 805.7,
"height": 35.28
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_quat": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_skewX": 0,
"_skewY": 0,
"_zIndex": 0,
"groupIndex": 0,
"_id": "",
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
0,
210,
-150,
0,
0,
0,
@@ -146,7 +130,19 @@
1,
1
]
}
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Label",
@@ -156,32 +152,26 @@
"__id__": 2
},
"_enabled": true,
"_srcBlendFactor": 1,
"_dstBlendFactor": 771,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_useOriginalSize": false,
"_string": "login.tips.loginSuccess",
"_N$string": "login.tips.loginSuccess",
"_fontSize": 30,
"_lineHeight": 30,
"_string": "Logged in successfully, loading game resources...",
"_N$string": "Logged in successfully, loading game resources...",
"_fontSize": 28,
"_lineHeight": 28,
"_enableWrapText": true,
"_N$file": null,
"_isSystemFontUsed": true,
"_spacingX": 0,
"_batchAsBitmap": false,
"_N$horizontalAlign": 1,
"_N$verticalAlign": 1,
"_N$fontFamily": "Arial",
"_N$overflow": 0,
"_id": ""
},
{
"__type__": "744dcs4DCdNprNhG0xwq6FK",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 2
},
"_enabled": true,
"_dataID": "login.tips.loginSuccess",
"_N$overflow": 3,
"_N$cacheMode": 0,
"_id": ""
},
{
@@ -204,14 +194,13 @@
},
"_children": [],
"_active": true,
"_level": 0,
"_components": [
{
"__id__": 7
"__id__": 6
}
],
"_prefab": {
"__id__": 8
"__id__": 7
},
"_opacity": 255,
"_color": {
@@ -231,24 +220,12 @@
"x": 0.5,
"y": 0.5
},
"_quat": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_skewX": 0,
"_skewY": 0,
"_zIndex": 0,
"groupIndex": 0,
"_id": "",
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
0,
333,
0,
0,
0,
0,
@@ -258,16 +235,29 @@
1,
1
]
}
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 6
"__id__": 5
},
"_enabled": true,
"_materials": [],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": null,
@@ -282,7 +272,6 @@
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_state": 0,
"_atlas": null,
"_id": ""
},
@@ -307,7 +296,7 @@
"_enabled": true,
"alignMode": 0,
"_target": null,
"_alignFlags": 20,
"_alignFlags": 18,
"_left": 0,
"_right": 0,
"_top": 0,

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

View File

@@ -1,34 +0,0 @@
{
"ver": "2.3.3",
"uuid": "825df908-a4cb-449d-9731-8ef53f3fd44f",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"platformSettings": {},
"subMetas": {
"MiniGame_Background": {
"ver": "1.0.4",
"uuid": "7838f276-ab48-445a-b858-937dd27d9520",
"rawTextureUuid": "825df908-a4cb-449d-9731-8ef53f3fd44f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 750,
"height": 1624,
"rawWidth": 750,
"rawHeight": 1624,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

View File

@@ -1,34 +0,0 @@
{
"ver": "2.3.3",
"uuid": "94b8bb09-e8ac-4402-a933-b79f01b5a813",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"platformSettings": {},
"subMetas": {
"MiniGame_Blackboard": {
"ver": "1.0.4",
"uuid": "334d4f93-b007-49e8-9268-35891d4f4ebb",
"rawTextureUuid": "94b8bb09-e8ac-4402-a933-b79f01b5a813",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 1024,
"height": 1920,
"rawWidth": 1024,
"rawHeight": 1920,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

View File

@@ -72,25 +72,25 @@
"__id__": 3
},
{
"__id__": 8
"__id__": 9
}
],
"_active": true,
"_components": [
{
"__id__": 37
},
{
"__id__": 38
},
{
"__id__": 39
},
{
"__id__": 40
},
{
"__id__": 41
},
{
"__id__": 42
},
{
"__id__": 43
},
{
"__id__": 44
}
],
"_prefab": null,
@@ -104,8 +104,8 @@
},
"_contentSize": {
"__type__": "cc.Size",
"width": 1024,
"height": 1920
"width": 960,
"height": 640
},
"_anchorPoint": {
"__type__": "cc.Vec2",
@@ -116,8 +116,8 @@
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
512,
960,
480,
320,
0,
0,
0,
@@ -158,7 +158,7 @@
"__id__": 5
},
{
"__id__": 36
"__id__": 39
}
],
"_prefab": null,
@@ -172,8 +172,8 @@
},
"_contentSize": {
"__type__": "cc.Size",
"width": 2048,
"height": 2048
"width": 960,
"height": 640
},
"_anchorPoint": {
"__type__": "cc.Vec2",
@@ -191,8 +191,8 @@
0,
0,
1,
1.5,
1.5,
1.2,
1.2,
1
]
},
@@ -234,6 +234,9 @@
"controlledCharacterPrefab": {
"__uuid__": "59bff7a2-23e1-4d69-bce7-afb37eae196a"
},
"fireballPrefab": {
"__uuid__": "d92d4831-cd65-4eb5-90bd-b77021aec35b"
},
"joystickInputControllerNode": {
"__id__": 6
},
@@ -244,10 +247,10 @@
"__uuid__": "670b477e-61a1-4778-879b-35913f7c79d2"
},
"boundRoomIdLabel": {
"__id__": 15
"__id__": 16
},
"countdownLabel": {
"__id__": 21
"__id__": 23
},
"resultPanelPrefab": {
"__uuid__": "c4cfe3bd-c59e-4d5b-95cb-c933b120e184"
@@ -256,7 +259,7 @@
"__uuid__": "32b8e752-8362-4783-a4a6-1160af8b7109"
},
"findingPlayerPrefab": {
"__uuid__": "3ed4c7bc-79d0-4075-a563-d5a58ae798f9"
"__uuid__": "dc804c5c-ff76-445e-ac69-52269055c3c5"
},
"countdownToBeginGamePrefab": {
"__uuid__": "230eeb1f-e0f9-4a41-ab6c-05b3771cbf3e"
@@ -268,6 +271,7 @@
"renderFrameIdLagTolerance": 4,
"jigglingEps1D": 0.001,
"bulletTriggerEnabled": true,
"closeOnForcedtoResyncNotSelf": true,
"_id": "d12gkAmppNlIzqcRDELa91"
},
{
@@ -279,13 +283,13 @@
},
"_children": [
{
"__id__": 30
"__id__": 33
}
],
"_active": true,
"_components": [
{
"__id__": 35
"__id__": 38
}
],
"_prefab": null,
@@ -311,16 +315,16 @@
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
0,
-500,
-199.439,
-172.557,
0,
0,
0,
0,
1,
0.66667,
0.66667,
0.66667
0.4,
0.4,
0.4
]
},
"_eulerAngles": {
@@ -338,30 +342,31 @@
},
{
"__type__": "cc.Node",
"_name": "WidgetsAboveAll",
"_name": "Interactive",
"_objFlags": 0,
"_parent": {
"__id__": 8
},
"_children": [
{
"__id__": 10
},
{
"__id__": 6
},
{
"__id__": 20
},
{
"__id__": 22
},
{
"__id__": 26
"__id__": 24
},
{
"__id__": 28
}
],
"_active": true,
"_components": [],
"_components": [
{
"__id__": 32
}
],
"_prefab": null,
"_opacity": 255,
"_color": {
@@ -408,6 +413,75 @@
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": "bb5Zj3NPxJgrEYDllBW7Gj"
},
{
"__type__": "cc.Node",
"_name": "WidgetsAboveAll",
"_objFlags": 0,
"_parent": {
"__id__": 9
},
"_children": [
{
"__id__": 11
},
{
"__id__": 7
}
],
"_active": true,
"_components": [
{
"__id__": 21
}
],
"_prefab": null,
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 1280,
"height": 1280
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
0,
0,
0,
0,
0,
0,
1,
1,
1,
1
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": "c6fPdAUURDX69j0zTeIFZv"
},
{
@@ -419,13 +493,13 @@
},
"_children": [
{
"__id__": 7
"__id__": 8
}
],
"_active": true,
"_components": [
{
"__id__": 9
"__id__": 10
}
],
"_prefab": null,
@@ -453,7 +527,7 @@
"array": [
0,
0,
215.81269742929726,
209.57814771583418,
0,
0,
0,
@@ -481,7 +555,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 8
"__id__": 9
},
"_enabled": true,
"_cullingMask": 4294967295,
@@ -517,20 +591,20 @@
"_name": "DebugInfo",
"_objFlags": 0,
"_parent": {
"__id__": 7
"__id__": 8
},
"_children": [
{
"__id__": 11
"__id__": 12
}
],
"_active": true,
"_components": [
{
"__id__": 18
"__id__": 19
},
{
"__id__": 19
"__id__": 20
}
],
"_prefab": null,
@@ -556,8 +630,8 @@
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
-478,
627,
-447.294,
135.702,
0,
0,
0,
@@ -586,23 +660,23 @@
"_name": "RoomIdIndicator",
"_objFlags": 0,
"_parent": {
"__id__": 10
"__id__": 11
},
"_children": [
{
"__id__": 12
"__id__": 13
},
{
"__id__": 14
"__id__": 15
}
],
"_active": false,
"_components": [
{
"__id__": 16
"__id__": 17
},
{
"__id__": 17
"__id__": 18
}
],
"_prefab": null,
@@ -658,13 +732,13 @@
"_name": "label",
"_objFlags": 0,
"_parent": {
"__id__": 11
"__id__": 12
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 13
"__id__": 14
}
],
"_prefab": null,
@@ -720,7 +794,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 12
"__id__": 13
},
"_enabled": true,
"_materials": [],
@@ -748,13 +822,13 @@
"_name": "BoundRoomIdLabel",
"_objFlags": 0,
"_parent": {
"__id__": 11
"__id__": 12
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 15
"__id__": 16
}
],
"_prefab": null,
@@ -810,7 +884,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 14
"__id__": 15
},
"_enabled": true,
"_materials": [],
@@ -838,7 +912,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 11
"__id__": 12
},
"_enabled": true,
"_layoutSize": {
@@ -871,7 +945,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 11
"__id__": 12
},
"_enabled": true,
"_materials": [],
@@ -901,7 +975,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 10
"__id__": 11
},
"_enabled": true,
"_materials": [],
@@ -927,7 +1001,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 10
"__id__": 11
},
"_enabled": true,
"_layoutSize": {
@@ -955,6 +1029,33 @@
"_N$affectedByScale": false,
"_id": "f6GkgYwn9JvKLqbGG1zmeD"
},
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 8
},
"_enabled": true,
"alignMode": 2,
"_target": null,
"_alignFlags": 18,
"_left": 0,
"_right": 0,
"_top": 0,
"_bottom": 0,
"_verticalCenter": 0,
"_horizontalCenter": 0,
"_isAbsLeft": true,
"_isAbsRight": true,
"_isAbsTop": true,
"_isAbsBottom": true,
"_isAbsHorizontalCenter": true,
"_isAbsVerticalCenter": true,
"_originalWidth": 0,
"_originalHeight": 0,
"_id": "aenJ9ZDDRKDoS7u5MxeZOb"
},
{
"__type__": "cc.Node",
"_name": "CountdownSeconds",
@@ -966,7 +1067,7 @@
"_active": true,
"_components": [
{
"__id__": 21
"__id__": 23
}
],
"_prefab": null,
@@ -993,7 +1094,7 @@
"ctor": "Float64Array",
"array": [
0,
591,
181.094,
0,
0,
0,
@@ -1022,7 +1123,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 20
"__id__": 22
},
"_enabled": true,
"_materials": [
@@ -1056,7 +1157,7 @@
},
"_children": [
{
"__id__": 23
"__id__": 25
}
],
"_active": true,
@@ -1084,16 +1185,16 @@
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
143.689,
-584.849,
178,
-179.607,
0,
0,
0,
0,
1,
0.66667,
0.66667,
0.66667
0.5,
0.5,
0.5
]
},
"_eulerAngles": {
@@ -1114,16 +1215,16 @@
"_name": "Background",
"_objFlags": 0,
"_parent": {
"__id__": 22
"__id__": 24
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 24
"__id__": 26
},
{
"__id__": 25
"__id__": 27
}
],
"_prefab": null,
@@ -1179,7 +1280,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 23
"__id__": 25
},
"_enabled": true,
"_materials": [
@@ -1213,7 +1314,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 23
"__id__": 25
},
"_enabled": true,
"alignMode": 0,
@@ -1244,7 +1345,7 @@
},
"_children": [
{
"__id__": 27
"__id__": 29
}
],
"_active": true,
@@ -1272,16 +1373,16 @@
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
370.368,
-424.647,
395,
-123.879,
0,
0,
0,
0,
1,
0.66667,
0.66667,
0.66667
0.5,
0.5,
0.5
]
},
"_eulerAngles": {
@@ -1302,16 +1403,16 @@
"_name": "Background",
"_objFlags": 0,
"_parent": {
"__id__": 26
"__id__": 28
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 28
"__id__": 30
},
{
"__id__": 29
"__id__": 31
}
],
"_prefab": null,
@@ -1367,7 +1468,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 27
"__id__": 29
},
"_enabled": true,
"_materials": [
@@ -1401,7 +1502,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 27
"__id__": 29
},
"_enabled": true,
"alignMode": 0,
@@ -1423,6 +1524,33 @@
"_originalHeight": 40,
"_id": "5bXB50moJH9aH7RcbRuSS5"
},
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 7
},
"_enabled": true,
"alignMode": 1,
"_target": null,
"_alignFlags": 20,
"_left": 0,
"_right": 0,
"_top": 0,
"_bottom": 640,
"_verticalCenter": 0,
"_horizontalCenter": 0,
"_isAbsLeft": true,
"_isAbsRight": true,
"_isAbsTop": true,
"_isAbsBottom": true,
"_isAbsHorizontalCenter": true,
"_isAbsVerticalCenter": true,
"_originalWidth": 0,
"_originalHeight": 0,
"_id": "60S5//1JxMULAtkfxKep87"
},
{
"__type__": "cc.Node",
"_name": "JoystickBG",
@@ -1432,16 +1560,16 @@
},
"_children": [
{
"__id__": 31
"__id__": 34
}
],
"_active": true,
"_components": [
{
"__id__": 33
"__id__": 36
},
{
"__id__": 34
"__id__": 37
}
],
"_prefab": null,
@@ -1497,13 +1625,13 @@
"_name": "Joystick",
"_objFlags": 0,
"_parent": {
"__id__": 30
"__id__": 33
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 32
"__id__": 35
}
],
"_prefab": null,
@@ -1559,7 +1687,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 31
"__id__": 34
},
"_enabled": true,
"_materials": [
@@ -1593,7 +1721,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 30
"__id__": 33
},
"_enabled": true,
"_materials": [
@@ -1627,7 +1755,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 30
"__id__": 33
},
"_enabled": true,
"alignMode": 0,
@@ -1684,21 +1812,11 @@
"__id__": 3
},
"_enabled": true,
"BGMEffect": {
"__uuid__": "64a79efa-97de-4cb5-b2a9-01500c60573a"
},
"crashedByTrapBullet": {
"__uuid__": "1d604e42-8cee-466f-884d-e74cae21ce3b"
},
"highScoreTreasurePicked": {
"__uuid__": "0164d22c-d965-461f-867e-b30e2d56cc5c"
},
"treasurePicked": {
"__uuid__": "7704b97e-6367-420c-b7af-d0750a2bbb30"
},
"countDown10SecToEnd": {
"__uuid__": "261d1d7d-a5cc-4cb7-a737-194427055fd4"
},
"BGMEffect": null,
"crashedByTrapBullet": null,
"highScoreTreasurePicked": null,
"treasurePicked": null,
"countDown10SecToEnd": null,
"mapNode": {
"__id__": 3
},
@@ -1714,8 +1832,8 @@
"_enabled": true,
"_designResolution": {
"__type__": "cc.Size",
"width": 1024,
"height": 1920
"width": 960,
"height": 640
},
"_fitWidth": true,
"_fitHeight": false,
@@ -1756,9 +1874,9 @@
"__id__": 2
},
"_enabled": true,
"alignMode": 0,
"alignMode": 1,
"_target": null,
"_alignFlags": 0,
"_alignFlags": 18,
"_left": 6240,
"_right": -4000,
"_top": -8320,
@@ -1790,10 +1908,10 @@
"__id__": 3
},
"stickhead": {
"__id__": 31
"__id__": 34
},
"base": {
"__id__": 30
"__id__": 33
},
"joyStickEps": 0.1,
"magicLeanLowerBound": 0.414,
@@ -1814,10 +1932,10 @@
"linearMovingEps": 0.1,
"scaleByEps": 0.0375,
"btnA": {
"__id__": 22
"__id__": 24
},
"btnB": {
"__id__": 26
"__id__": 28
},
"_id": "e9oVYTr7ROlpp/IrNjBUmR"
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -12,9 +12,13 @@ window.ATK_CHARACTER_STATE = {
BlownUp1: [8, "BlownUp1"],
LayDown1: [9, "LayDown1"], // The last frame of "LayDown1" should have a simliar boundingbox with the first frame of "GetUp1", otherwise the animation would seem odd
GetUp1: [10, "GetUp1"],
Atk2: [11, "Atk2"],
Atk3: [12, "Atk3"],
Atk4: [13, "Atk4"],
Atk2: [11, "Atk2"],
Atk3: [12, "Atk3"],
Atk4: [13, "Atk4"],
Atk5: [14, "Atk5"],
Dashing: [15, "Dashing"],
OnWall: [16, "OnWall"],
TurnAround1: [17, "TurnAround1"],
};
window.ATK_CHARACTER_STATE_ARR = [];
@@ -30,6 +34,8 @@ window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.In
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.BlownUp1[0]);
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.LayDown1[0]);
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.GetUp1[0]);
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.Dashing[0]);
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.OnWall[0]);
window.ATK_CHARACTER_STATE_IN_AIR_SET = new Set();
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.InAirIdle1NoJump[0]);
@@ -37,6 +43,7 @@ window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.InAirIdle1B
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.InAirAtk1[0]);
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.InAirAtked1[0]);
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.BlownUp1[0]);
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.OnWall[0]);
/*
Kindly note that the use of dragonBones anim is an informed choice for the feasibility of "gotoAndPlayByFrame", which is a required feature by "Map.rollbackAndChase". You might find that "cc.Animation" -- the traditional frame anim -- can also suffice this requirement, yet if we want to develop 3D frontend in the future, working with skeletal anim will make a smoother transition.
@@ -78,16 +85,24 @@ cc.Class({
updateCharacterAnim(rdfPlayer, prevRdfPlayer, forceAnimSwitch, chConfig) {
// As this function might be called after many frames of a rollback, it's possible that the playing animation was predicted, different from "prevRdfPlayer.CharacterState" but same as "newCharacterState". More granular checks are needed to determine whether we should interrupt the playing animation.
let newCharacterState = rdfPlayer.CharacterState;
// Update directions
if (this.animComp && this.animComp.node) {
if (0 > rdfPlayer.DirX) {
this.animNode.scaleX = (-1.0);
} else if (0 < rdfPlayer.DirX) {
this.animNode.scaleX = (1.0);
this.animNode.scaleX = (+1.0);
}
if (ATK_CHARACTER_STATE.OnWall[0] == newCharacterState || ATK_CHARACTER_STATE.TurnAround1[0] == newCharacterState) {
if (0 < rdfPlayer.OnWallNormX) {
this.animNode.scaleX = (-1.0);
} else {
this.animNode.scaleX = (+1.0);
}
}
}
let newCharacterState = rdfPlayer.CharacterState;
let newAnimName = window.ATK_CHARACTER_STATE_ARR[newCharacterState][1];
let playingAnimName = null;
let underlyingAnimationCtrl = null;
@@ -138,7 +153,7 @@ cc.Class({
let frameIdxInAnim = rdfPlayer.FramesInChState;
if (window.ATK_CHARACTER_STATE.InAirIdle1ByJump == newCharacterState && null != chConfig) {
frameIdxInAnim = chConfig.InAirIdleFrameIdxTurningPoint + (frameIdxInAnim - chConfig.InAirIdleFrameIdxTurningPoint) % chConfig.InAirIdleFrameIdxTurnedCycle; // TODO: Anyway to avoid using division here?
}
}
let fromTime = (frameIdxInAnim / targetClip.sample); // TODO: Anyway to avoid using division here?
this.animComp.play(newAnimName, fromTime);
},

View File

@@ -0,0 +1,36 @@
window.BULLET_STATE = {
Startup: 0,
Active: 1,
Exploding: 2,
};
cc.Class({
extends: cc.Component,
properties: {
animNode: {
type: cc.Node,
default: null
},
},
updateAnim(newAnimName, frameIdxInAnim, dirX, spontaneousLooping, rdf, newAnimIdx) {
this.animComp = this.effAnimNode.getComponent(cc.Animation);
// Update directions
if (this.animComp && this.animComp.node) {
if (0 > dirX) {
this.animNode.scaleX = (-1.0);
} else if (0 < dirX) {
this.animNode.scaleX = (1.0);
}
}
const currentClip = this.animComp.currentClip;
if (true == spontaneousLooping && (null != currentClip && currentClip.name == newAnimName)) {
return;
}
const targetClip = this.animComp.getClips()[newAnimIdx];
let fromTime = (frameIdxInAnim / targetClip.sample); // TODO: Anyway to avoid using division here?
this.animComp.play(newAnimName, fromTime);
},
});

View File

@@ -1,6 +1,6 @@
{
"ver": "1.0.5",
"uuid": "247b7613-6c6e-4f01-b1d6-5f8f041b5688",
"uuid": "a4b909c4-56a8-4b70-b6ea-b7f928077747",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,

View File

@@ -1,37 +1,34 @@
cc.Class({
extends: cc.Component,
extends: cc.Component,
properties: {
mapNode: {
type: cc.Node,
default: null
},
speed: {
type: cc.Float,
default: 500
},
properties: {
mapNode: {
type: cc.Node,
default: null
},
onLoad () {
this.mainCamera = this.mapNode.parent.getChildByName("Main Camera").getComponent(cc.Camera);
this.mapScriptIns = this.mapNode.getComponent("Map");
speed: {
type: cc.Float,
default: 500
},
},
start() {},
onLoad() {
this.mainCamera = this.mapNode.parent.getChildByName("Main Camera").getComponent(cc.Camera);
this.mapScriptIns = this.mapNode.getComponent("Map");
},
update(dt) {
const self = this;
if (!self.mainCamera) return;
if (!self.mapScriptIns) return;
if (!self.mapScriptIns.selfPlayerInfo) return;
if (!self.mapScriptIns.playerRichInfoDict) return;
const selfPlayerRichInfo = self.mapScriptIns.playerRichInfoDict.get(self.mapScriptIns.selfPlayerInfo.Id);
if (!selfPlayerRichInfo) return;
const selfPlayerNode = selfPlayerRichInfo.node;
if (!selfPlayerNode) return;
const pDiff = selfPlayerNode.position.sub(self.mainCamera.node.position);
pDiff.normalizeSelf();
const newCamPos = self.mainCamera.node.position.add(pDiff.mul(dt*self.speed));
self.mainCamera.node.setPosition(newCamPos);
}
start() {},
update(dt) {
const self = this;
if (!self.mainCamera) return;
if (!self.mapScriptIns) return;
if (!self.mapScriptIns.selfPlayerInfo) return;
if (!self.mapScriptIns.playerRichInfoDict) return;
const selfPlayerRichInfo = self.mapScriptIns.playerRichInfoDict.get(self.mapScriptIns.selfPlayerInfo.Id);
if (!selfPlayerRichInfo) return;
const selfPlayerNode = selfPlayerRichInfo.node;
if (!selfPlayerNode) return;
self.mapNode.setPosition(cc.v2().sub(selfPlayerNode.position));
}
});

View File

@@ -14,10 +14,6 @@ cc.Class({
type: cc.Node,
default: null
},
myAvatarNode: {
type: cc.Node,
default: null
},
exitBtnNode: {
type: cc.Node,
default: null
@@ -25,8 +21,7 @@ cc.Class({
},
// LIFE-CYCLE CALLBACKS:
onLoad() {
},
onLoad() {},
init() {
if (null != this.firstPlayerInfoNode) {
@@ -70,29 +65,20 @@ cc.Class({
const playerInfoNode = this.playersInfoNode[playerMeta.joinIndex];
if (null == playerInfoNode) {
cc.error("There's no playerInfoNode for joinIndex == ", joinIndex, ", as `this.playerInfoNode` is currently ", this.playersInfoNode);
}
}
playerInfoNode.active = true;
if (2 == playerMeta.joinIndex) {
if (null != this.findingAnimNode) {
if (null != this.findingAnimNode) {
this.findingAnimNode.active = false;
}
}
}
//显示自己的头像名称以及他人的头像名称
for (let i in playerMetas) {
const playerMeta = playerMetas[i];
console.log("Showing playerMeta:", playerMeta);
const playerInfoNode = this.playersInfoNode[playerMeta.joinIndex];
(() => { //远程加载头像
let remoteUrl = playerMeta.avatar;
if (remoteUrl == null || remoteUrl == '') {
cc.log(`No avatar to show for :`);
cc.log(playerMeta);
}
})();
function isEmptyString(str) {
return str == null || str == ''
}

View File

@@ -0,0 +1,29 @@
const Bullet = require("./Bullet");
cc.Class({
extends: Bullet,
ctor() {
this.lastUsed = -1;
this.bulletLocalId = -1;
this.speciesName = null;
},
setSpecies(speciesName, fireballBullet, rdf) {
if (speciesName == this.speciesName) return;
if (null != this.speciesName) {
for (let k in this.animNode.children) {
const child = this.children[k];
if (!child.active) continue;
if (child == effAnimNode || child.name == speciesName) continue;
child.active = false;
}
}
this.speciesName = speciesName;
this.effAnimNode = this.animNode.getChildByName(this.speciesName);
this.effAnimNode.active = true;
},
onLoad() {},
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "e66a2a91-9916-469e-a4b2-54cc0bcba3f0",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -68,6 +68,8 @@ cc.Class({
// LIFE-CYCLE CALLBACKS:
onLoad() {
cc.view.setOrientation(cc.macro.ORIENTATION_AUTO);
cc.view.enableAutoFullScreen(true);
window.atFirstLocationHref = window.location.href.split('#')[0];
const self = this;

View File

@@ -2,6 +2,7 @@ const i18n = require('LanguageData');
i18n.init(window.language); // languageID should be equal to the one we input in New Language ID input field
const RingBuffer = require('./RingBuffer');
const PriorityQueue = require("./PriorityQueue");
window.ALL_MAP_STATES = {
VISUAL: 0, // For free dragging & zooming.
@@ -44,6 +45,10 @@ cc.Class({
type: cc.Prefab,
default: null,
},
fireballPrefab: {
type: cc.Prefab,
default: null,
},
joystickInputControllerNode: {
type: cc.Node,
default: null
@@ -129,7 +134,7 @@ cc.Class({
previousSelfInput = (null == previousInputFrameDownsync ? null : previousInputFrameDownsync.InputList[joinIndex - 1]);
if (null != existingInputFrame) {
// This could happen upon either [type#1] or [type#2] forceConfirmation, where "refRenderFrame" is accompanied by some "inputFrameDownsyncs". The check here also guarantees that we don't override history
console.log(`noDelayInputFrameId=${inputFrameId} already exists in recentInputCache: recentInputCache=${self._stringifyRecentInputCache(false)}`);
//console.log(`noDelayInputFrameId=${inputFrameId} already exists in recentInputCache: recentInputCache=${self._stringifyRecentInputCache(false)}`);
return [previousSelfInput, existingInputFrame.InputList[joinIndex - 1]];
}
@@ -287,6 +292,30 @@ cc.Class({
self.playerRichInfoDict = new Map();
// Clearing previous info of all players. [ENDS]
// Clearing cached fireball rendering nodes [BEGINS]
if (null != self.cachedFireballs) {
while (!self.cachedFireballs.isEmpty()) {
const v = self.cachedFireballs.pop();
if (v && v.node && v.node.parent) {
v.node.parent.removeChild(v.node);
}
}
} else {
self.cachedFireballs = new PriorityQueue();
}
for (let k = 0; k < 1000; k++) {
const newFireballNode = cc.instantiate(self.fireballPrefab);
const newFireball = newFireballNode.getComponent("Fireball");
newFireballNode.setPosition(cc.v2(Number.MAX_VALUE, Number.MAX_VALUE));
safelyAddChild(self.node, newFireballNode);
setLocalZOrder(newFireballNode, 10);
newFireball.lastUsed = -1;
newFireball.bulletLocalId = -1;
const initLookupKey = -(k + 1); // there's definitely no suck "bulletLocalId"
self.cachedFireballs.push(newFireball.lastUsed, newFireball, initLookupKey);
}
// Clearing cached fireball rendering nodes [ENDS]
self.renderFrameId = 0; // After battle started
self.bulletBattleLocalIdCounter = 0;
self.lastAllConfirmedInputFrameId = -1;
@@ -380,11 +409,14 @@ cc.Class({
},
onLoad() {
cc.view.setOrientation(cc.macro.ORIENTATION_LANDSCAPE);
cc.view.enableAutoFullScreen(true);
const self = this;
window.mapIns = self;
window.forceBigEndianFloatingNumDecoding = self.forceBigEndianFloatingNumDecoding;
self.showCriticalCoordinateLabels = true;
self.showCriticalCoordinateLabels = false;
console.warn("+++++++ Map onLoad()");
@@ -444,7 +476,6 @@ cc.Class({
console.log(`Received parsedBattleColliderInfo via ws`);
// TODO: Upon reconnection, the backend might have already been sending down data that'd trigger "onRoomDownsyncFrame & onInputFrameDownsyncBatch", but frontend could reject those data due to "battleState != PlayerBattleState.ACTIVE".
Object.assign(self, parsedBattleColliderInfo);
self.tooFastDtIntervalMillis = 0.5 * self.rollbackEstimatedDtMillis;
const tiledMapIns = self.node.getComponent(cc.TiledMap);
@@ -578,19 +609,19 @@ cc.Class({
const jsPlayersArr = new Array(pbRdf.playersArr.length).fill(null);
for (let k = 0; k < pbRdf.playersArr.length; ++k) {
const pbPlayer = pbRdf.playersArr[k];
const jsPlayer = gopkgs.NewPlayerDownsyncJs(pbPlayer.id, pbPlayer.virtualGridX, pbPlayer.virtualGridY, pbPlayer.dirX, pbPlayer.dirY, pbPlayer.velX, pbPlayer.velY, pbPlayer.framesToRecover, pbPlayer.framesInChState, pbPlayer.activeSkillId, pbPlayer.activeSkillHit, pbPlayer.framesInvinsible, pbPlayer.speed, pbPlayer.battleState, pbPlayer.characterState, pbPlayer.joinIndex, pbPlayer.hp, pbPlayer.maxHp, pbPlayer.colliderRadius, pbPlayer.inAir);
const jsPlayer = gopkgs.NewPlayerDownsyncJs(pbPlayer.id, pbPlayer.virtualGridX, pbPlayer.virtualGridY, pbPlayer.dirX, pbPlayer.dirY, pbPlayer.velX, pbPlayer.velY, pbPlayer.framesToRecover, pbPlayer.framesInChState, pbPlayer.activeSkillId, pbPlayer.activeSkillHit, pbPlayer.framesInvinsible, pbPlayer.speed, pbPlayer.battleState, pbPlayer.characterState, pbPlayer.joinIndex, pbPlayer.hp, pbPlayer.maxHp, pbPlayer.colliderRadius, pbPlayer.inAir, pbPlayer.onWall, pbPlayer.onWallNormX, pbPlayer.onWallNormY, pbPlayer.capturedByInertia, pbPlayer.bulletTeamId, pbPlayer.chCollisionTeamId);
jsPlayersArr[k] = jsPlayer;
}
const jsMeleeBulletsArr = new Array(pbRdf.meleeBullets.length).fill(null);
for (let k = 0; k < pbRdf.meleeBullets.length; ++k) {
const pbBullet = pbRdf.meleeBullets[k];
const jsMeleeBullet = gopkgs.NewMeleeBulletJs(pbBullet.bulletLocalId, pbBullet.originatedRenderFrameId, pbBullet.offenderJoinIndex, pbBullet.startupFrames, pbBullet.cancellableStFrame, pbBullet.cancellableEdFrame, pbBullet.activeFrames, pbBullet.hitStunFrames, pbBullet.blockStunFrames, pbBullet.pushbackVelX, pbBullet.pushbackVelY, pbBullet.damage, pbBullet.selfLockVelX, pbBullet.selfLockVelY, pbBullet.hitboxOffsetX, pbBullet.hitboxOffsetY, pbBullet.hitboxSizeX, pbBullet.hitboxSizeY, pbBullet.blowUp);
const jsMeleeBullet = gopkgs.NewMeleeBulletJs(pbBullet.bulletLocalId, pbBullet.originatedRenderFrameId, pbBullet.offenderJoinIndex, pbBullet.startupFrames, pbBullet.cancellableStFrame, pbBullet.cancellableEdFrame, pbBullet.activeFrames, pbBullet.hitStunFrames, pbBullet.blockStunFrames, pbBullet.pushbackVelX, pbBullet.pushbackVelY, pbBullet.damage, pbBullet.selfLockVelX, pbBullet.selfLockVelY, pbBullet.hitboxOffsetX, pbBullet.hitboxOffsetY, pbBullet.hitboxSizeX, pbBullet.hitboxSizeY, pbBullet.blowUp, pbBullet.teamId, pbBullet.blState, pbBullet.framesInBlState, pbBullet.explosionFrames, pbBullet.speciesId);
jsMeleeBulletsArr[k] = jsMeleeBullet;
}
const jsFireballBulletsArr = new Array(pbRdf.fireballBullets.length).fill(null);
for (let k = 0; k < pbRdf.fireballBullets.length; ++k) {
const pbBullet = pbRdf.fireballBullets[k];
const jsFireballBullet = gopkgs.NewFireballBulletJs(pbBullet.bulletLocalId, pbBullet.originatedRenderFrameId, pbBullet.offenderJoinIndex, pbBullet.startupFrames, pbBullet.cancellableStFrame, pbBullet.cancellableEdFrame, pbBullet.activeFrames, pbBullet.hitStunFrames, pbBullet.blockStunFrames, pbBullet.pushbackVelX, pbBullet.pushbackVelY, pbBullet.damage, pbBullet.selfLockVelX, pbBullet.selfLockVelY, pbBullet.hitboxOffsetX, pbBullet.hitboxOffsetY, pbBullet.hitboxSizeX, pbBullet.hitboxSizeY, pbBullet.blowUp, pbBullet.teamId, pbBullet.virtualGridX, pbBullet.virtualGridY, pbBullet.dirX, pbBullet.dirY, pbBullet.velX, pbBullet.velY, pbBullet.speed);
const jsFireballBullet = gopkgs.NewFireballBulletJs(pbBullet.bulletLocalId, pbBullet.originatedRenderFrameId, pbBullet.offenderJoinIndex, pbBullet.startupFrames, pbBullet.cancellableStFrame, pbBullet.cancellableEdFrame, pbBullet.activeFrames, pbBullet.hitStunFrames, pbBullet.blockStunFrames, pbBullet.pushbackVelX, pbBullet.pushbackVelY, pbBullet.damage, pbBullet.selfLockVelX, pbBullet.selfLockVelY, pbBullet.hitboxOffsetX, pbBullet.hitboxOffsetY, pbBullet.hitboxSizeX, pbBullet.hitboxSizeY, pbBullet.blowUp, pbBullet.teamId, pbBullet.virtualGridX, pbBullet.virtualGridY, pbBullet.dirX, pbBullet.dirY, pbBullet.velX, pbBullet.velY, pbBullet.speed, pbBullet.blState, pbBullet.framesInBlState, pbBullet.explosionFrames, pbBullet.speciesId);
jsFireballBulletsArr[k] = jsFireballBullet;
}
@@ -691,6 +722,8 @@ cc.Class({
equalPlayers(lhs, rhs) {
if (null == lhs || null == rhs) return false;
if (null == lhs && null != rhs) return false;
if (null != lhs && null == rhs) return false;
if (lhs.VirtualGridX != rhs.VirtualGridX) return false;
if (lhs.VirtualGridY != rhs.VirtualGridY) return false;
if (lhs.DirX != rhs.DirX) return false;
@@ -709,20 +742,43 @@ cc.Class({
equalMeleeBullets(lhs, rhs) {
if (null == lhs || null == rhs) return false;
if (lhs.battleLocalId != rhs.battleLocalId) return false;
if (lhs.offenderPlayerId != rhs.offenderPlayerId) return false;
if (lhs.offenderJoinIndex != rhs.offenderJoinIndex) return false;
if (lhs.originatedRenderFrameId != rhs.originatedRenderFrameId) return false;
if (null == lhs && null != rhs) return false;
if (null != lhs && null == rhs) return false;
if (lhs.BattleAttr.BulletLocalId != rhs.BattleAttr.BulletLocalId) return false;
if (lhs.BattleAttr.OffenderJoinIndex != rhs.BattleAttr.OffenderJoinIndex) return false;
if (lhs.BattleAttr.OriginatedRenderFrameId != rhs.BattleAttr.OriginatedRenderFrameId) return false;
return true;
},
equalFireballBullets(lhs, rhs) {
if (null == lhs || null == rhs) return false;
if (null == lhs && null != rhs) return false;
if (null != lhs && null == rhs) return false;
if (lhs.BattleAttr.BulletLocalId != rhs.BattleAttr.BulletLocalId) return false;
if (lhs.BattleAttr.OffenderJoinIndex != rhs.BattleAttr.OffenderJoinIndex) return false;
if (lhs.BattleAttr.OriginatedRenderFrameId != rhs.BattleAttr.OriginatedRenderFrameId) return false;
if (lhs.VirtualGridX != rhs.Bullet.VirtualGridX) return false;
if (lhs.VirtualGridY != rhs.Bullet.VirtualGridY) return false;
if (lhs.DirX != rhs.DirX) return false;
if (lhs.DirY != rhs.DirY) return false;
if (lhs.VelX != rhs.VelX) return false;
if (lhs.VelY != rhs.VelY) return false;
if (lhs.Speed != rhs.Speed) return false;
return true;
},
equalRoomDownsyncFrames(lhs, rhs) {
if (null == lhs || null == rhs) return false;
for (let k in lhs.players) {
if (!this.equalPlayers(lhs.players[k], rhs.players[k])) return false;
for (let k in lhs.PlayersArr) {
if (!this.equalPlayers(lhs.PlayersArr[k], rhs.PlayersArr[k])) return false;
}
for (let k in lhs.meleeBullets) {
if (!this.equalMeleeBullets(lhs.meleeBullets[k], rhs.meleeBullets[k])) return false;
for (let k in lhs.MeleeBullets) {
if (!this.equalMeleeBullets(lhs.MeleeBullets[k], rhs.MeleeBullets[k])) return false;
}
for (let k in lhs.fireballBullet) {
if (!this.equalFireballBullets(lhs.FireballBullets[k], rhs.FireballBullets[k])) return false;
}
return true;
},
@@ -783,13 +839,41 @@ cc.Class({
--------------------------------------------------------
*/
// The actual rollback-and-chase would later be executed in update(dt).
console.warn(`Mismatched input detected, resetting chaserRenderFrameId: ${self.chaserRenderFrameId}->${renderFrameId1} by firstPredictedYetIncorrectInputFrameId: ${firstPredictedYetIncorrectInputFrameId}
console.log(`Mismatched input detected, resetting chaserRenderFrameId: ${self.chaserRenderFrameId}->${renderFrameId1} by firstPredictedYetIncorrectInputFrameId: ${firstPredictedYetIncorrectInputFrameId}
lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId}
recentInputCache=${self._stringifyRecentInputCache(false)}
batchInputFrameIdRange=[${batch[0].inputFrameId}, ${batch[batch.length - 1].inputFrameId}]`);
self.chaserRenderFrameId = renderFrameId1;
},
onPeerInputFrameUpsync(peerJoinIndex, batch /* []*pb.InputFrameDownsync */ ) {
// TODO: find some kind of synchronization mechanism against "getOrPrefabInputFrameUpsync"!
// See `<proj-root>/ConcerningEdgeCases.md` for why this method exists.
if (null == batch) {
return;
}
const self = this;
if (!self.recentInputCache) {
return;
}
if (ALL_BATTLE_STATES.IN_SETTLEMENT == self.battleState) {
return;
}
//console.log(`Received peer inputFrameUpsync batch w/ inputFrameId in [${batch[0].inputFrameId}, ${batch[batch.length - 1].inputFrameId}] for prediction assistance`);
for (let k in batch) {
const inputFrameDownsync = batch[k];
const inputFrameDownsyncId = inputFrameDownsync.inputFrameId;
if (inputFrameDownsyncId <= self.lastAllConfirmedInputFrameId) {
continue;
}
self.getOrPrefabInputFrameUpsync(inputFrameDownsyncId); // Make sure that inputFrame exists locally
const existingInputFrame = self.recentInputCache.GetByFrameId(inputFrameDownsyncId);
existingInputFrame.InputList[peerJoinIndex - 1] = inputFrameDownsync.inputList[peerJoinIndex - 1]; // No need to change "confirmedList", leave it to "onInputFrameDownsyncBatch" -- we're just helping prediction here
self.recentInputCache.SetByFrameId(existingInputFrame, inputFrameDownsyncId);
}
},
onPlayerAdded(rdf /* pb.RoomDownsyncFrame */ ) {
const self = this;
// Update the "finding player" GUI and show it if not previously present
@@ -854,21 +938,28 @@ batchInputFrameIdRange=[${batch[0].inputFrameId}, ${batch[batch.length - 1].inpu
update(dt) {
const self = this;
if (ALL_BATTLE_STATES.IN_BATTLE == self.battleState) {
const elapsedMillisSinceLastFrameIdTriggered = performance.now() - self.lastRenderFrameIdTriggeredAt;
if (elapsedMillisSinceLastFrameIdTriggered < self.tooFastDtIntervalMillis) {
// [WARNING] We should avoid a frontend ticking too fast to prevent cheating, as well as ticking too slow to cause a "resync avalanche" that impacts user experience!
// console.debug("Avoiding too fast frame@renderFrameId=", self.renderFrameId, ": elapsedMillisSinceLastFrameIdTriggered=", elapsedMillisSinceLastFrameIdTriggered);
return;
}
/*
[WARNING] Different devices might differ in the rate of calling "update(dt)", and the game engine is responsible of keeping this rate statistically constant.
Significantly different rates of calling "update(dt)" among players in a same battle would result in frequent [type#1 forceConfirmation], if you have any doubt on troubles caused by this, sample the FPS curve from all players in that battle.
Kindly note that Significantly different network bandwidths or delay fluctuations would result in frequent [type#1 forceConfirmation] too, but CAUSE FROM DIFFERENT LOCAL "update(dt)" RATE SHOULD BE THE FIRST TO INVESTIGATE AND ELIMINATE -- because we have control on it, but no one has control on the internet.
*/
try {
let st = performance.now();
const noDelayInputFrameId = gopkgs.ConvertToNoDelayInputFrameId(self.renderFrameId);
let prevSelfInput = null,
currSelfInput = null;
const noDelayInputFrameId = gopkgs.ConvertToNoDelayInputFrameId(self.renderFrameId);
if (gopkgs.ShouldGenerateInputFrameUpsync(self.renderFrameId)) {
[prevSelfInput, currSelfInput] = self.getOrPrefabInputFrameUpsync(noDelayInputFrameId);
}
const delayedInputFrameId = gopkgs.ConvertToDelayedInputFrameId(self.renderFrameId);
if (null == self.recentInputCache.GetByFrameId(delayedInputFrameId)) {
// Possible edge case after resync, kindly note that it's OK to prefab a "future inputFrame" here, because "sendInputFrameUpsyncBatch" would be capped by "noDelayInputFrameId from self.renderFrameId".
self.getOrPrefabInputFrameUpsync(delayedInputFrameId);
}
let t0 = performance.now();
if (self.shouldSendInputFrameUpsyncBatch(prevSelfInput, currSelfInput, self.lastUpsyncInputFrameId, noDelayInputFrameId)) {
// TODO: Is the following statement run asynchronously in an implicit manner? Should I explicitly run it asynchronously?
@@ -899,17 +990,17 @@ batchInputFrameIdRange=[${batch[0].inputFrameId}, ${batch[batch.length - 1].inpu
}
*/
// [WARNING] Don't try to get "prevRdf(i.e. renderFrameId == latest-1)" by "self.recentRenderCache.getByFrameId(...)" here, as the cache might have been updated by asynchronous "onRoomDownsyncFrame(...)" calls!
if (self.othersForcedDownsyncRenderFrameDict.has(rdf.id)) {
const delayedInputFrameId = gopkgs.ConvertToDelayedInputFrameId(rdf.id);
const othersForcedDownsyncRenderFrame = self.othersForcedDownsyncRenderFrameDict.get(rdf.id);
if (self.othersForcedDownsyncRenderFrameDict.has(rdf.Id)) {
const delayedInputFrameId = gopkgs.ConvertToDelayedInputFrameId(rdf.Id);
const othersForcedDownsyncRenderFrame = self.othersForcedDownsyncRenderFrameDict.get(rdf.Id);
if (self.lastAllConfirmedInputFrameId >= delayedInputFrameId && !self.equalRoomDownsyncFrames(othersForcedDownsyncRenderFrame, rdf)) {
console.warn(`Mismatched render frame@rdf.id=${rdf.id} w/ inputFrameId=${delayedInputFrameId}:
console.warn(`Mismatched render frame@rdf.id=${rdf.Id} w/ inputFrameId=${delayedInputFrameId}:
rdf=${JSON.stringify(rdf)}
othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame)}`);
// closeWSConnection(constants.RET_CODE.CLIENT_MISMATCHED_RENDER_FRAME, "");
// self.onManualRejoinRequired("[DEBUG] CLIENT_MISMATCHED_RENDER_FRAME");
rdf = othersForcedDownsyncRenderFrame;
self.othersForcedDownsyncRenderFrameDict.delete(rdf.id);
self.othersForcedDownsyncRenderFrameDict.delete(rdf.Id);
}
}
self.applyRoomDownsyncFrameDynamics(rdf, prevRdf);
@@ -1053,6 +1144,77 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
playerRichInfo.scriptIns.updateCharacterAnim(currPlayerDownsync, prevRdfPlayer, false, chConfig);
}
// Move all to infinitely far away first
for (let k in self.cachedFireballs.list) {
const pqNode = self.cachedFireballs.list[k];
const fireball = pqNode.value;
fireball.node.setPosition(cc.v2(Number.MAX_VALUE, Number.MAX_VALUE));
}
for (let k in rdf.MeleeBullets) {
const meleeBullet = rdf.MeleeBullets[k];
const isExploding = (window.BULLET_STATE.Exploding == meleeBullet.BlState);
if (isExploding) {
let pqNode = self.cachedFireballs.popAny(meleeBullet.BattleAttr.BulletLocalId);
let speciesName = `MeleeExplosion`;
let animName = `MeleeExplosion${meleeBullet.Bullet.SpeciesId}`;
const offender = rdf.PlayersArr[meleeBullet.BattleAttr.OffenderJoinIndex - 1];
let xfac = 1; // By now, straight Punch offset doesn't respect "y-axis"
if (0 > offender.DirX) {
xfac = -1;
}
const [wx, wy] = gopkgs.VirtualGridToWorldPos(offender.VirtualGridX + xfac * meleeBullet.Bullet.HitboxOffsetX, offender.VirtualGridY);
if (null == pqNode) {
pqNode = self.cachedFireballs.pop();
//console.log(`@rdf.Id=${rdf.Id}, origRdfId=${meleeBullet.BattleAttr.OriginatedRenderFrameId}, startupFrames=${meleeBullet.Bullet.StartupFrames}, using a new fireball node for rendering for bulletLocalId=${meleeBullet.BattleAttr.BulletLocalId} at wpos=(${wx},${wy})`);
} else {
//console.log(`@rdf.Id=${rdf.Id}, origRdfId=${meleeBullet.BattleAttr.OriginatedRenderFrameId}, startupFrames=${meleeBullet.Bullet.StartupFrames}, using a cached fireball node for rendering for bulletLocalId=${meleeBullet.BattleAttr.BulletLocalId} at wpos=(${wx},${wy})`);
}
const cachedFireball = pqNode.value;
cachedFireball.setSpecies(speciesName, meleeBullet, rdf);
const newAnimIdx = meleeBullet.Bullet.SpeciesId - 1;
cachedFireball.updateAnim(animName, meleeBullet.FramesInBlState, offender.DirX, false, rdf, newAnimIdx);
cachedFireball.lastUsed = self.renderFrameId;
cachedFireball.bulletLocalId = meleeBullet.BattleAttr.BulletLocalId;
cachedFireball.node.setPosition(cc.v2(wx, wy));
self.cachedFireballs.push(cachedFireball.lastUsed, cachedFireball, meleeBullet.BattleAttr.BulletLocalId);
} else {
//console.log(`@rdf.Id=${rdf.Id}, origRdfId=${meleeBullet.BattleAttr.OriginatedRenderFrameId}, startupFrames=${meleeBullet.Bullet.StartupFrames}, activeFrames=${meleeBullet.Bullet.ActiveFrames}, not rendering melee node for bulletLocalId=${meleeBullet.BattleAttr.BulletLocalId}`);
}
}
for (let k in rdf.FireballBullets) {
const fireballBullet = rdf.FireballBullets[k];
const isExploding = (window.BULLET_STATE.Exploding == fireballBullet.BlState);
if (gopkgs.IsFireballBulletActive(fireballBullet, rdf) || isExploding) {
let pqNode = self.cachedFireballs.popAny(fireballBullet.BattleAttr.BulletLocalId);
let speciesName = `Fireball${fireballBullet.Bullet.SpeciesId}`;
let animName = (BULLET_STATE.Exploding == fireballBullet.BlState ? `Fireball${fireballBullet.Bullet.SpeciesId}Explosion` : speciesName);
const [wx, wy] = gopkgs.VirtualGridToWorldPos(fireballBullet.VirtualGridX, fireballBullet.VirtualGridY);
if (null == pqNode) {
pqNode = self.cachedFireballs.pop();
//console.log(`@rdf.Id=${rdf.Id}, origRdfId=${fireballBullet.BattleAttr.OriginatedRenderFrameId}, startupFrames=${fireballBullet.Bullet.StartupFrames}, using a new fireball node for rendering for bulletLocalId=${fireballBullet.BattleAttr.BulletLocalId} at wpos=(${wx},${wy})`);
} else {
//console.log(`@rdf.Id=${rdf.Id}, origRdfId=${fireballBullet.BattleAttr.OriginatedRenderFrameId}, startupFrames=${fireballBullet.Bullet.StartupFrames}, using a cached fireball node for rendering for bulletLocalId=${fireballBullet.BattleAttr.BulletLocalId} at wpos=(${wx},${wy})`);
}
const cachedFireball = pqNode.value;
cachedFireball.setSpecies(speciesName, fireballBullet, rdf);
const spontaneousLooping = !isExploding;
const newAnimIdx = (spontaneousLooping ? 0 : 1);
cachedFireball.updateAnim(animName, fireballBullet.FramesInBlState, fireballBullet.DirX, spontaneousLooping, rdf, newAnimIdx);
cachedFireball.lastUsed = self.renderFrameId;
cachedFireball.bulletLocalId = fireballBullet.BattleAttr.BulletLocalId;
cachedFireball.node.setPosition(cc.v2(wx, wy));
self.cachedFireballs.push(cachedFireball.lastUsed, cachedFireball, fireballBullet.BattleAttr.BulletLocalId);
} else {
//console.log(`@rdf.Id=${rdf.Id}, origRdfId=${fireballBullet.BattleAttr.OriginatedRenderFrameId}, startupFrames=${fireballBullet.Bullet.StartupFrames}, activeFrames=${fireballBullet.Bullet.ActiveFrames}, not rendering fireball node for bulletLocalId=${fireballBullet.BattleAttr.BulletLocalId}`);
}
}
// Update countdown
self.countdownNanos = self.battleDurationNanos - self.renderFrameId * self.rollbackEstimatedDtNanos;
if (self.countdownNanos <= 0) {
@@ -1070,13 +1232,26 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
throw `Couldn't find renderFrame for i=${i} to rollback (are you using Firefox?), self.renderFrameId=${self.renderFrameId}, lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId}, might've been interruptted by onRoomDownsyncFrame`;
}
const j = gopkgs.ConvertToDelayedInputFrameId(i);
const delayedInputFrame = self.recentInputCache.GetByFrameId(j); // Don't make prediction here, the inputFrameDownsyncs in recentInputCache was already predicted while prefabbing
if (null == delayedInputFrame) {
// Shouldn't happen!
throw `Failed to get cached delayedInputFrame for i=${i}, j=${j}, renderFrameId=${self.renderFrameId}, lastUpsyncInputFrameId=${self.lastUpsyncInputFrameId}, lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId}, chaserRenderFrameId=${self.chaserRenderFrameId}; recentRenderCache=${self._stringifyRecentRenderCache(false)}, recentInputCache=${self._stringifyRecentInputCache(false)}`;
}
const delayedInputFrame = self.recentInputCache.GetByFrameId(j);
/*
const prevJ = gopkgs.ConvertToDelayedInputFrameId(i - 1);
const prevDelayedInputFrame = self.recentInputCache.GetByFrameId(prevJ);
const prevBtnALevel = (null == prevDelayedInputFrame ? 0 : ((prevDelayedInputFrame.InputList[self.selfPlayerInfo.JoinIndex - 1] >> 4) & 1));
const btnALevel = ((delayedInputFrame.InputList[self.selfPlayerInfo.JoinIndex - 1] >> 4) & 1);
if (
ATK_CHARACTER_STATE.Atk1[0] == currRdf.PlayersArr[self.selfPlayerInfo.JoinIndex - 1].CharacterState
||
ATK_CHARACTER_STATE.Atk2[0] == currRdf.PlayersArr[self.selfPlayerInfo.JoinIndex - 1].CharacterState
) {
console.log(`rdf.Id=${i}, (btnALevel,j)=(${btnALevel},${j}), (prevBtnALevel,prevJ) is (${prevBtnALevel},${prevJ}), in cancellable atk!`);
}
if (btnALevel > 0) {
if (btnALevel > prevBtnALevel) {
console.log(`rdf.Id=${i}, rising edge of btnA triggered`);
}
}
*/
const jPrev = gopkgs.ConvertToDelayedInputFrameId(i - 1);
if (self.frameDataLoggingEnabled) {
const actuallyUsedInputClone = delayedInputFrame.InputList.slice();
const inputFrameDownsyncClone = {
@@ -1174,7 +1349,12 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
playerDownsyncStr(playerDownsync) {
if (null == playerDownsync) return "";
return `{${playerDownsync.JoinIndex},${playerDownsync.VirtualGridX},${playerDownsync.VirtualGridY},${playerDownsync.VelX},${playerDownsync.VelY},${playerDownsync.FramesToRecover},${playerDownsync.InAir ? 1 : 0}}`;
return `{${playerDownsync.JoinIndex},${playerDownsync.VirtualGridX},${playerDownsync.VirtualGridY},${playerDownsync.VelX},${playerDownsync.VelY},${playerDownsync.FramesToRecover},${playerDownsync.InAir ? 1 : 0},${playerDownsync.OnWall ? 1 : 0}}`;
},
fireballDownsyncStr(fireball) {
if (null == fireball) return "";
return `{${fireball.BattleAttr.BulletLocalId},${fireball.BattleAttr.OriginatedRenderFrameId},${fireball.BattleAttr.OffenderJoinIndex},${fireball.VirtualGridX},${fireball.VirtualGridY},${fireball.VelX},${fireball.VelY},${fireball.DirX},${fireball.DirY},${fireball.Bullet.HitboxSizeX},${fireball.Bullet.HitboxSizeY}}`;
},
inputFrameDownsyncStr(inputFrameDownsync) {
@@ -1203,8 +1383,13 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
for (let k in rdf.PlayersArr) {
playersStrBldr.push(self.playerDownsyncStr(rdf.PlayersArr[k]));
}
const fireballsStrBldr = [];
for (let k in rdf.FireballBullets) {
fireballsStrBldr.push(self.fireballDownsyncStr(rdf.FireballBullets[k]));
}
s.push(`rdfId:${i}
players:[${playersStrBldr.join(',')}]
fireballs:[${fireballsStrBldr.join(',')}]
actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`);
}
@@ -1242,6 +1427,7 @@ actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`);
case ATK_CHARACTER_STATE.BlownUp1[0]:
case ATK_CHARACTER_STATE.InAirIdle1NoJump[0]:
case ATK_CHARACTER_STATE.InAirIdle1ByJump[0]:
case ATK_CHARACTER_STATE.OnWall[0]:
[colliderWidth, colliderHeight] = [player.ColliderRadius * 2, player.ColliderRadius * 2];
break;
}
@@ -1262,12 +1448,8 @@ actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`);
for (let k in rdf.MeleeBullets) {
const meleeBullet = rdf.MeleeBullets[k];
if (
meleeBullet.Bullet.OriginatedRenderFrameId + meleeBullet.Bullet.StartupFrames <= rdf.Id
&&
meleeBullet.Bullet.OriginatedRenderFrameId + meleeBullet.Bullet.StartupFrames + meleeBullet.Bullet.ActiveFrames > rdf.Id
) {
const offender = rdf.PlayersArr[meleeBullet.Bullet.OffenderJoinIndex - 1];
if (gopkgs.IsMeleeBulletActive(meleeBullet, rdf)) {
const offender = rdf.PlayersArr[meleeBullet.BattleAttr.OffenderJoinIndex - 1];
if (1 == offender.JoinIndex) {
g2.strokeColor = cc.Color.BLUE;
} else {
@@ -1294,12 +1476,8 @@ actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`);
for (let k in rdf.FireballBullets) {
const fireballBullet = rdf.FireballBullets[k];
if (
fireballBullet.Bullet.OriginatedRenderFrameId + fireballBullet.Bullet.StartupFrames <= rdf.Id
&&
fireballBullet.Bullet.OriginatedRenderFrameId + fireballBullet.Bullet.StartupFrames + fireballBullet.Bullet.ActiveFrames > rdf.Id
) {
const offender = rdf.PlayersArr[fireballBullet.Bullet.OffenderJoinIndex - 1];
if (gopkgs.IsFireballBulletActive(fireballBullet, rdf)) {
const offender = rdf.PlayersArr[fireballBullet.BattleAttr.OffenderJoinIndex - 1];
if (1 == offender.JoinIndex) {
g2.strokeColor = cc.Color.BLUE;
} else {

View File

@@ -11,9 +11,11 @@ cc.Class({
},
onLoad() {
cc.view.setOrientation(cc.macro.ORIENTATION_LANDSCAPE);
cc.view.enableAutoFullScreen(true);
const self = this;
window.mapIns = self;
self.showCriticalCoordinateLabels = true;
self.showCriticalCoordinateLabels = false;
const mapNode = self.node;
const canvasNode = mapNode.parent;
@@ -29,7 +31,7 @@ cc.Class({
/** Init required prefab ended. */
self.inputFrameUpsyncDelayTolerance = 2;
self.collisionMinStep = 8;
self.collisionMinStep = 2;
self.renderCacheSize = 1024;
self.serverFps = 60;
@@ -92,9 +94,11 @@ cc.Class({
const p1Vpos = gopkgs.WorldToVirtualGridPos(boundaryObjs.playerStartingPositions[0].x, boundaryObjs.playerStartingPositions[0].y);
const p2Vpos = gopkgs.WorldToVirtualGridPos(boundaryObjs.playerStartingPositions[1].x, boundaryObjs.playerStartingPositions[1].y);
const speedV = gopkgs.WorldToVirtualGridPos(1.0, 0);
const colliderRadiusV = gopkgs.WorldToVirtualGridPos(12.0, 0);
const speciesIdList = [4096, 1];
const chConfigsOrderedByJoinIndex = gopkgs.GetCharacterConfigsOrderedByJoinIndex(speciesIdList);
const startRdf = window.pb.protos.RoomDownsyncFrame.create({
id: window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START,
playersArr: [
@@ -103,7 +107,7 @@ cc.Class({
joinIndex: 1,
virtualGridX: p1Vpos[0],
virtualGridY: p1Vpos[1],
speed: speedV[0],
speed: chConfigsOrderedByJoinIndex[0].Speed,
colliderRadius: colliderRadiusV[0],
characterState: window.ATK_CHARACTER_STATE.InAirIdle1NoJump[0],
framesToRecover: 0,
@@ -112,13 +116,14 @@ cc.Class({
velX: 0,
velY: 0,
inAir: true,
onWall: false,
}),
window.pb.protos.PlayerDownsync.create({
id: 11,
joinIndex: 2,
virtualGridX: p2Vpos[0],
virtualGridY: p2Vpos[1],
speed: speedV[0],
speed: chConfigsOrderedByJoinIndex[1].Speed,
colliderRadius: colliderRadiusV[0],
characterState: window.ATK_CHARACTER_STATE.InAirIdle1NoJump[0],
framesToRecover: 0,
@@ -127,9 +132,10 @@ cc.Class({
velX: 0,
velY: 0,
inAir: true,
onWall: false,
}),
],
speciesIdList: [4096, 0],
speciesIdList: speciesIdList,
});
self.selfPlayerInfo = {
@@ -150,7 +156,7 @@ cc.Class({
if (elapsedMillisSinceLastFrameIdTriggered < self.tooFastDtIntervalMillis) {
// [WARNING] We should avoid a frontend ticking too fast to prevent cheating, as well as ticking too slow to cause a "resync avalanche" that impacts user experience!
// console.debug("Avoiding too fast frame@renderFrameId=", self.renderFrameId, ": elapsedMillisSinceLastFrameIdTriggered=", elapsedMillisSinceLastFrameIdTriggered);
return;
//return;
}
try {
let st = performance.now();

View File

@@ -12,32 +12,15 @@ var BinaryHeap = function (customCompare) {
* @private
*/
this.list = [];
this.lookupKeyToIndex = {};
if (customCompare) {
this.compare = customCompare;
}
};
/**
* Builds a heap with the provided keys and values, this will discard the
* heap's current data.
*
* @param {Array} keys An array of keys.
* @param {Array} values An array of values. This must be the same size as the
* key array.
*/
BinaryHeap.prototype.buildHeap = function (keys, values) {
if (typeof values !== 'undefined' && values.length !== keys.length) {
throw new Error('Key array must be the same length as value array');
}
var nodeArray = [];
for (var i = 0; i < keys.length; i++) {
nodeArray.push(new Node(keys[i], values ? values[i] : undefined));
}
buildHeapFromNodeArray(this, nodeArray);
BinaryHeap.prototype.contains = function (lookupKey) {
return null != this.lookupKeyToIndex[lookupKey];
};
/**
@@ -45,6 +28,7 @@ BinaryHeap.prototype.buildHeap = function (keys, values) {
*/
BinaryHeap.prototype.clear = function () {
this.list.length = 0;
this.lookupKeyToIndex = null;
};
/**
@@ -53,15 +37,20 @@ BinaryHeap.prototype.clear = function () {
* @return {Node} node The heap's minimum node or undefined if the heap is
* empty.
*/
BinaryHeap.prototype.extractMinimum = function () {
if (!this.list.length) {
return undefined;
BinaryHeap.prototype.pop = function () {
if (0 == this.list.length) {
return null;
}
if (this.list.length === 1) {
if (1 == this.list.length) {
delete this.lookupKeyToIndex[Object.keys(this.lookupKeyToIndex)[0]];
return this.list.shift();
}
var min = this.list[0];
delete this.lookupKeyToIndex[min.lookupKey];
this.list[0] = this.list.pop();
this.lookupKeyToIndex[this.list[0].lookupKey] = 0;
heapify(this, 0);
return min;
};
@@ -72,8 +61,8 @@ BinaryHeap.prototype.extractMinimum = function () {
* @return {Node} node The heap's minimum node or undefined if the heap is
* empty.
*/
BinaryHeap.prototype.findMinimum = function () {
return this.isEmpty() ? undefined : this.list[0];
BinaryHeap.prototype.top = function () {
return this.isEmpty() ? null : this.list[0];
};
/**
@@ -83,25 +72,79 @@ BinaryHeap.prototype.findMinimum = function () {
* @param {Object} value The value to insert.
* @return {Node} node The inserted node.
*/
BinaryHeap.prototype.insert = function (key, value) {
BinaryHeap.prototype.push = function (key, value, lookupKey) {
var i = this.list.length;
var node = new Node(key, value);
var node = new Node(key, value, lookupKey);
this.list.push(node);
var parent = getParent(i);
while (typeof parent !== 'undefined' &&
this.compare(this.list[i], this.list[parent]) < 0) {
swap(this.list, i, parent);
i = parent;
parent = getParent(i);
this.lookupKeyToIndex[lookupKey] = i;
let u = getParent(i);
while (null != u && this.compare(this.list[i], this.list[u]) < 0) {
swap(this.list, i, u, this.lookupKeyToIndex);
i = u;
u = getParent(i);
}
return node;
};
BinaryHeap.prototype.update = function (lookupKey, newKey, newValue) {
if (null == this.lookupKeyToIndex[lookupKey]) return null;
var i = this.lookupKeyToIndex[lookupKey];
this.list[i].key = newKey;
this.list[i].value = newValue;
let u = getParent(i);
if (null != u && this.compare(this.list[i], this.list[u]) < 0) {
while (null != u && this.compare(this.list[i], this.list[u]) < 0) {
swap(this.list, i, u, this.lookupKeyToIndex);
i = u;
u = getParent(i);
}
} else {
heapify(this, i);
}
};
BinaryHeap.prototype.popAny = function (lookupKey) {
if (null == this.lookupKeyToIndex[lookupKey]) return null;
if (0 == this.list.length) {
return null;
}
if (1 == this.list.length) {
delete this.lookupKeyToIndex[Object.keys(this.lookupKeyToIndex)[0]];
return this.list.shift();
}
var i = this.lookupKeyToIndex[lookupKey];
var old = this.list[i];
delete this.lookupKeyToIndex[old.lookupKey];
this.list[i] = this.list.pop();
this.lookupKeyToIndex[this.list[i].lookupKey] = i;
let u = getParent(i);
if (null != u && this.compare(this.list[i], this.list[u]) < 0) {
while (null != u && this.compare(this.list[i], this.list[u]) < 0) {
swap(this.list, i, u, this.lookupKeyToIndex);
i = u;
u = getParent(i);
}
} else {
heapify(this, i);
}
return old;
};
/**
* @return {boolean} Whether the heap is empty.
*/
BinaryHeap.prototype.isEmpty = function () {
return !this.list.length;
return 0 == this.list.length;
};
/**
@@ -111,16 +154,6 @@ BinaryHeap.prototype.size = function () {
return this.list.length;
};
/**
* Joins another heap to this one.
*
* @param {BinaryHeap} otherHeap The other heap.
*/
BinaryHeap.prototype.union = function (otherHeap) {
var array = this.list.concat(otherHeap.list);
buildHeapFromNodeArray(this, array);
};
/**
* Compares two nodes with each other.
*
@@ -147,34 +180,27 @@ BinaryHeap.prototype.compare = function (a, b) {
* @param {number} i The index of the node to heapify.
*/
function heapify(heap, i) {
var l = getLeft(i);
var r = getRight(i);
var smallest = i;
if (l < heap.list.length &&
heap.compare(heap.list[l], heap.list[i]) < 0) {
smallest = l;
}
if (r < heap.list.length &&
heap.compare(heap.list[r], heap.list[smallest]) < 0) {
smallest = r;
}
if (smallest !== i) {
swap(heap.list, i, smallest);
heapify(heap, smallest);
}
}
let cur = i;
let smallest = -1;
while (cur != smallest) {
const l = getLeft(cur);
const r = getRight(cur);
smallest = cur;
if (l < heap.list.length &&
heap.compare(heap.list[l], heap.list[smallest]) < 0) {
smallest = l;
}
if (r < heap.list.length &&
heap.compare(heap.list[r], heap.list[smallest]) < 0) {
smallest = r;
}
/**
* Builds a heap from a node array, this will discard the heap's current data.
*
* @private
* @param {BinaryHeap} heap The heap to override.
* @param {Node[]} nodeArray The array of nodes for the new heap.
*/
function buildHeapFromNodeArray(heap, nodeArray) {
heap.list = nodeArray;
for (var i = Math.floor(heap.list.length / 2); i >= 0; i--) {
heapify(heap, i);
if (smallest !== cur) {
swap(heap.list, cur, smallest, heap.lookupKeyToIndex);
cur = smallest;
smallest = -1;
}
}
}
@@ -186,10 +212,16 @@ function buildHeapFromNodeArray(heap, nodeArray) {
* @param {number} a The index of the first element.
* @param {number} b The index of the second element.
*/
function swap(array, a, b) {
function swap(array, a, b, lookupKeyToIndex) {
var aLookupKey = array[a].lookupKey;
var bLookupKey = array[b].lookupKey;
var temp = array[a];
array[a] = array[b];
array[b] = temp;
lookupKeyToIndex[aLookupKey] = b;
lookupKeyToIndex[bLookupKey] = a;
}
/**
@@ -200,8 +232,8 @@ function swap(array, a, b) {
* @return {number} The index of the node's parent.
*/
function getParent(i) {
if (i === 0) {
return undefined;
if (0 == i) {
return null;
}
return Math.floor((i - 1) / 2);
}
@@ -235,9 +267,10 @@ function getRight(i) {
* @param {Object} key The key of the new node.
* @param {Object} value The value of the new node.
*/
function Node(key, value) {
function Node(key, value, lookupKey) {
this.key = key;
this.value = value;
this.lookupKey = lookupKey;
}
module.exports = BinaryHeap;

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "20a75b4a-e220-42cd-bab4-9fc63a289b3f",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -11,14 +11,6 @@ cc.Class({
type: cc.Object,
default: null
},
myAvatarNode: {
type: cc.Node,
default: null,
},
myNameNode: {
type: cc.Node,
default: null,
},
rankingNodes: {
type: [cc.Node],
default: [],
@@ -46,22 +38,6 @@ cc.Class({
showPlayerInfo(playerRichInfoDict) {
this.showRanking(playerRichInfoDict);
this.showMyAvatar();
this.showMyName();
},
showMyName() {
const selfPlayerInfo = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
let name = 'No name';
if (null == selfPlayerInfo.displayName || "" == selfPlayerInfo.displayName) {
name = selfPlayerInfo.name;
} else {
name = selfPlayerInfo.displayName;
}
if (!this.myNameNode) return;
const myNameNodeLabel = this.myNameNode.getComponent(cc.Label);
if (!myNameNodeLabel || null == name) return;
myNameNodeLabel.string = name;
},
showRanking(playerRichInfoDict) {
@@ -115,42 +91,6 @@ cc.Class({
}
},
showMyAvatar() {
const self = this;
const selfPlayerInfo = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
let remoteUrl = selfPlayerInfo.avatar;
if (remoteUrl == null || remoteUrl == '') {
cc.log(`No avatar to show for myself, check storage.`);
return;
} else {
cc.loader.load({
url: remoteUrl,
type: 'jpg'
}, function(err, texture) {
if (err != null || texture == null) {
console.log(err);
} else {
const sf = new cc.SpriteFrame();
sf.setTexture(texture);
self.myAvatarNode.getComponent(cc.Sprite).spriteFrame = sf;
}
});
}
},
showRibbon(winnerInfo, ribbonNode) {
const selfPlayerInfo = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
const texture = (selfPlayerInfo.playerId == winnerInfo.id) ? "textures/resultPanel/WinRibbon" : "textures/resultPanel/loseRibbon";
cc.loader.loadRes(texture, cc.SpriteFrame, function(err, spriteFrame) {
if (err) {
console.log(err);
return;
}
ribbonNode.getComponent(cc.Sprite).spriteFrame = spriteFrame;
});
},
onClose(evt) {
if (this.node.parent) {
this.node.parent.removeChild(this.node);

View File

@@ -106,8 +106,13 @@ cc.Class({
this.cachedBtnDownLevel = 0;
this.cachedBtnLeftLevel = 0;
this.cachedBtnRightLevel = 0;
this.realtimeBtnALevel = 0;
this.cachedBtnALevel = 0;
this.btnAEdgeTriggerLock = false;
this.realtimeBtnBLevel = 0;
this.cachedBtnBLevel = 0;
this.btnBEdgeTriggerLock = false;
this.canvasNode = this.mapNode.parent;
this.mainCameraNode = this.canvasNode.getChildByName("Main Camera"); // Cannot drag and assign the `mainCameraNode` from CocosCreator EDITOR directly, otherwise it'll cause an infinite loading time, till v2.1.0.
@@ -163,31 +168,25 @@ cc.Class({
if (self.btnA) {
self.btnA.on(cc.Node.EventType.TOUCH_START, function(evt) {
self.cachedBtnALevel = 1;
evt.target.runAction(cc.scaleTo(0.1, 0.3));
self._triggerEdgeBtnA(true);
});
self.btnA.on(cc.Node.EventType.TOUCH_END, function(evt) {
self.cachedBtnALevel = 0;
evt.target.runAction(cc.scaleTo(0.1, 1.0));
self._triggerEdgeBtnA(false);
});
self.btnA.on(cc.Node.EventType.TOUCH_CANCEL, function(evt) {
self.cachedBtnALevel = 0;
evt.target.runAction(cc.scaleTo(0.1, 1.0));
self._triggerEdgeBtnA(false);
});
}
if (self.btnB) {
self.btnB.on(cc.Node.EventType.TOUCH_START, function(evt) {
self.cachedBtnBLevel = 1;
evt.target.runAction(cc.scaleTo(0.1, 0.3));
self._triggerEdgeBtnB(true);
});
self.btnB.on(cc.Node.EventType.TOUCH_END, function(evt) {
self.cachedBtnBLevel = 0;
evt.target.runAction(cc.scaleTo(0.1, 1.0));
self._triggerEdgeBtnB(false);
});
self.btnB.on(cc.Node.EventType.TOUCH_CANCEL, function(evt) {
self.cachedBtnBLevel = 0;
evt.target.runAction(cc.scaleTo(0.1, 1.0));
self._triggerEdgeBtnB(false);
});
}
@@ -195,22 +194,38 @@ cc.Class({
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, function(evt) {
switch (evt.keyCode) {
case cc.macro.KEY.w:
self.cachedBtnUpLevel = 0;
self.cachedBtnDownLevel = 0;
self.cachedBtnLeftLevel = 0;
self.cachedBtnRightLevel = 0;
self.cachedBtnUpLevel = 1;
break;
case cc.macro.KEY.s:
self.cachedBtnUpLevel = 0;
self.cachedBtnDownLevel = 0;
self.cachedBtnLeftLevel = 0;
self.cachedBtnRightLevel = 0;
self.cachedBtnDownLevel = 1;
break;
case cc.macro.KEY.a:
self.cachedBtnUpLevel = 0;
self.cachedBtnDownLevel = 0;
self.cachedBtnLeftLevel = 0;
self.cachedBtnRightLevel = 0;
self.cachedBtnLeftLevel = 1;
break;
case cc.macro.KEY.d:
self.cachedBtnUpLevel = 0;
self.cachedBtnDownLevel = 0;
self.cachedBtnLeftLevel = 0;
self.cachedBtnRightLevel = 0;
self.cachedBtnRightLevel = 1;
break;
case cc.macro.KEY.h:
self.cachedBtnALevel = 1;
self._triggerEdgeBtnA(true);
break;
case cc.macro.KEY.j:
self.cachedBtnBLevel = 1;
self._triggerEdgeBtnB(true);
break;
default:
break;
@@ -232,10 +247,10 @@ cc.Class({
self.cachedBtnRightLevel = 0;
break;
case cc.macro.KEY.h:
self.cachedBtnALevel = 0;
self._triggerEdgeBtnA(false);
break;
case cc.macro.KEY.j:
self.cachedBtnBLevel = 0;
self._triggerEdgeBtnB(false);
break;
default:
break;
@@ -448,6 +463,12 @@ cc.Class({
const discretizedDir = this.discretizeDirection(this.stickhead.x, this.stickhead.y, this.joyStickEps).encodedIdx; // There're only 9 dirs, thus using only the lower 4-bits
const btnALevel = (this.cachedBtnALevel << 4);
const btnBLevel = (this.cachedBtnBLevel << 5);
this.cachedBtnALevel = this.realtimeBtnALevel;
this.cachedBtnBLevel = this.realtimeBtnBLevel;
this.btnAEdgeTriggerLock = false;
this.btnBEdgeTriggerLock = false;
return (btnBLevel + btnALevel + discretizedDir);
},
@@ -466,4 +487,30 @@ cc.Class({
btnBLevel: btnBLevel,
});
},
_triggerEdgeBtnA(rising) {
this.realtimeBtnALevel = (rising ? 1 : 0);
if (!this.btnAEdgeTriggerLock && (1 - this.realtimeBtnALevel) == this.cachedBtnALevel) {
this.cachedBtnALevel = this.realtimeBtnALevel;
this.btnAEdgeTriggerLock = true;
}
if (rising) {
this.btnA.runAction(cc.scaleTo(0.1, 0.3));
} else {
this.btnA.runAction(cc.scaleTo(0.1, 0.5));
}
},
_triggerEdgeBtnB(rising, evt) {
this.realtimeBtnBLevel = (rising ? 1 : 0);
if (!this.btnBEdgeTriggerLock && (1 - this.realtimeBtnBLevel) == this.cachedBtnBLevel) {
this.cachedBtnBLevel = this.realtimeBtnBLevel;
this.btnBEdgeTriggerLock = true;
}
if (rising) {
this.btnB.runAction(cc.scaleTo(0.1, 0.3));
} else {
this.btnB.runAction(cc.scaleTo(0.1, 0.5));
}
},
});

View File

@@ -11,6 +11,7 @@ window.DOWNSYNC_MSG_ACT_HB_REQ = 1;
window.DOWNSYNC_MSG_ACT_INPUT_BATCH = 2;
window.DOWNSYNC_MSG_ACT_BATTLE_STOPPED = 3;
window.DOWNSYNC_MSG_ACT_FORCED_RESYNC = 4;
window.DOWNSYNC_MSG_ACT_PEER_INPUT_BATCH = 5;
window.sendSafely = function(msgStr) {
/**
@@ -65,6 +66,7 @@ window.handleHbRequirements = function(resp) {
}
if (window.handleBattleColliderInfo) {
window.initSecondarySession(null, window.boundRoomId);
window.handleBattleColliderInfo(resp.bciFrame);
}
};
@@ -130,8 +132,6 @@ window.initPersistentSessionClient = function(onopenCb, expectedRoomId) {
}
}
const currentHistoryState = window.history && window.history.state ? window.history.state : {};
const clientSession = new WebSocket(urlToConnect);
clientSession.binaryType = 'arraybuffer'; // Make 'event.data' of 'onmessage' an "ArrayBuffer" instead of a "Blob"
@@ -240,3 +240,56 @@ window.clearLocalStorageAndBackToLoginScene = function(shouldRetainBoundRoomIdIn
cc.director.loadScene('login');
};
// For secondary ws session
window.initSecondarySession = function(onopenCb, boundRoomId) {
if (window.secondarySession && window.secondarySession.readyState == WebSocket.OPEN) {
if (null != onopenCb) {
onopenCb();
}
return;
}
const selfPlayerStr = cc.sys.localStorage.getItem("selfPlayer");
const selfPlayer = null == selfPlayerStr ? null : JSON.parse(selfPlayerStr);
const intAuthToken = null == selfPlayer ? "" : selfPlayer.intAuthToken;
let urlToConnect = backendAddress.PROTOCOL.replace('http', 'ws') + '://' + backendAddress.HOST + ":" + backendAddress.PORT + "/tsrhtSecondary?isSecondary=true&intAuthToken=" + intAuthToken + "&boundRoomId=" + boundRoomId;
const clientSession = new WebSocket(urlToConnect);
clientSession.binaryType = 'arraybuffer'; // Make 'event.data' of 'onmessage' an "ArrayBuffer" instead of a "Blob"
clientSession.onopen = function(evt) {
console.warn("The secondary WS clientSession is opened.");
window.secondarySession = clientSession;
if (null == onopenCb) return;
onopenCb();
};
clientSession.onmessage = function(evt) {
if (null == evt || null == evt.data) {
return;
}
try {
const resp = window.pb.protos.WsResp.decode(new Uint8Array(evt.data));
//console.log(`Got non-empty onmessage decoded: resp.act=${resp.act}`);
switch (resp.act) {
case window.DOWNSYNC_MSG_ACT_PEER_INPUT_BATCH:
mapIns.onPeerInputFrameUpsync(resp.peerJoinIndex, resp.inputFrameDownsyncBatch);
break;
default:
break;
}
} catch (e) {
console.error("Secondary ws session, unexpected error when parsing data of:", evt.data, e);
}
};
clientSession.onerror = function(evt) {
console.error("Secondary ws session, error caught on the WS clientSession: ", evt);
};
clientSession.onclose = function(evt) {
// [WARNING] The callback "onclose" might be called AFTER the webpage is refreshed with "1001 == evt.code".
console.warn(`Secondary ws session is closed: evt=${JSON.stringify(evt)}, evt.code=${evt.code}`);
};
};

View File

@@ -1216,6 +1216,10 @@ $root.protos = (function() {
* @property {number|null} [framesInvinsible] PlayerDownsync framesInvinsible
* @property {number|null} [bulletTeamId] PlayerDownsync bulletTeamId
* @property {number|null} [chCollisionTeamId] PlayerDownsync chCollisionTeamId
* @property {boolean|null} [onWall] PlayerDownsync onWall
* @property {number|null} [onWallNormX] PlayerDownsync onWallNormX
* @property {number|null} [onWallNormY] PlayerDownsync onWallNormY
* @property {boolean|null} [capturedByInertia] PlayerDownsync capturedByInertia
* @property {string|null} [name] PlayerDownsync name
* @property {string|null} [displayName] PlayerDownsync displayName
* @property {string|null} [avatar] PlayerDownsync avatar
@@ -1436,6 +1440,38 @@ $root.protos = (function() {
*/
PlayerDownsync.prototype.chCollisionTeamId = 0;
/**
* PlayerDownsync onWall.
* @member {boolean} onWall
* @memberof protos.PlayerDownsync
* @instance
*/
PlayerDownsync.prototype.onWall = false;
/**
* PlayerDownsync onWallNormX.
* @member {number} onWallNormX
* @memberof protos.PlayerDownsync
* @instance
*/
PlayerDownsync.prototype.onWallNormX = 0;
/**
* PlayerDownsync onWallNormY.
* @member {number} onWallNormY
* @memberof protos.PlayerDownsync
* @instance
*/
PlayerDownsync.prototype.onWallNormY = 0;
/**
* PlayerDownsync capturedByInertia.
* @member {boolean} capturedByInertia
* @memberof protos.PlayerDownsync
* @instance
*/
PlayerDownsync.prototype.capturedByInertia = false;
/**
* PlayerDownsync name.
* @member {string} name
@@ -1534,6 +1570,14 @@ $root.protos = (function() {
writer.uint32(/* id 24, wireType 0 =*/192).int32(message.bulletTeamId);
if (message.chCollisionTeamId != null && Object.hasOwnProperty.call(message, "chCollisionTeamId"))
writer.uint32(/* id 25, wireType 0 =*/200).int32(message.chCollisionTeamId);
if (message.onWall != null && Object.hasOwnProperty.call(message, "onWall"))
writer.uint32(/* id 26, wireType 0 =*/208).bool(message.onWall);
if (message.onWallNormX != null && Object.hasOwnProperty.call(message, "onWallNormX"))
writer.uint32(/* id 27, wireType 0 =*/216).int32(message.onWallNormX);
if (message.onWallNormY != null && Object.hasOwnProperty.call(message, "onWallNormY"))
writer.uint32(/* id 28, wireType 0 =*/224).int32(message.onWallNormY);
if (message.capturedByInertia != null && Object.hasOwnProperty.call(message, "capturedByInertia"))
writer.uint32(/* id 29, wireType 0 =*/232).bool(message.capturedByInertia);
if (message.name != null && Object.hasOwnProperty.call(message, "name"))
writer.uint32(/* id 997, wireType 2 =*/7978).string(message.name);
if (message.displayName != null && Object.hasOwnProperty.call(message, "displayName"))
@@ -1674,6 +1718,22 @@ $root.protos = (function() {
message.chCollisionTeamId = reader.int32();
break;
}
case 26: {
message.onWall = reader.bool();
break;
}
case 27: {
message.onWallNormX = reader.int32();
break;
}
case 28: {
message.onWallNormY = reader.int32();
break;
}
case 29: {
message.capturedByInertia = reader.bool();
break;
}
case 997: {
message.name = reader.string();
break;
@@ -1796,6 +1856,18 @@ $root.protos = (function() {
if (message.chCollisionTeamId != null && message.hasOwnProperty("chCollisionTeamId"))
if (!$util.isInteger(message.chCollisionTeamId))
return "chCollisionTeamId: integer expected";
if (message.onWall != null && message.hasOwnProperty("onWall"))
if (typeof message.onWall !== "boolean")
return "onWall: boolean expected";
if (message.onWallNormX != null && message.hasOwnProperty("onWallNormX"))
if (!$util.isInteger(message.onWallNormX))
return "onWallNormX: integer expected";
if (message.onWallNormY != null && message.hasOwnProperty("onWallNormY"))
if (!$util.isInteger(message.onWallNormY))
return "onWallNormY: integer expected";
if (message.capturedByInertia != null && message.hasOwnProperty("capturedByInertia"))
if (typeof message.capturedByInertia !== "boolean")
return "capturedByInertia: boolean expected";
if (message.name != null && message.hasOwnProperty("name"))
if (!$util.isString(message.name))
return "name: string expected";
@@ -1870,6 +1942,14 @@ $root.protos = (function() {
message.bulletTeamId = object.bulletTeamId | 0;
if (object.chCollisionTeamId != null)
message.chCollisionTeamId = object.chCollisionTeamId | 0;
if (object.onWall != null)
message.onWall = Boolean(object.onWall);
if (object.onWallNormX != null)
message.onWallNormX = object.onWallNormX | 0;
if (object.onWallNormY != null)
message.onWallNormY = object.onWallNormY | 0;
if (object.capturedByInertia != null)
message.capturedByInertia = Boolean(object.capturedByInertia);
if (object.name != null)
message.name = String(object.name);
if (object.displayName != null)
@@ -1918,6 +1998,10 @@ $root.protos = (function() {
object.framesInvinsible = 0;
object.bulletTeamId = 0;
object.chCollisionTeamId = 0;
object.onWall = false;
object.onWallNormX = 0;
object.onWallNormY = 0;
object.capturedByInertia = false;
object.name = "";
object.displayName = "";
object.avatar = "";
@@ -1972,6 +2056,14 @@ $root.protos = (function() {
object.bulletTeamId = message.bulletTeamId;
if (message.chCollisionTeamId != null && message.hasOwnProperty("chCollisionTeamId"))
object.chCollisionTeamId = message.chCollisionTeamId;
if (message.onWall != null && message.hasOwnProperty("onWall"))
object.onWall = message.onWall;
if (message.onWallNormX != null && message.hasOwnProperty("onWallNormX"))
object.onWallNormX = message.onWallNormX;
if (message.onWallNormY != null && message.hasOwnProperty("onWallNormY"))
object.onWallNormY = message.onWallNormY;
if (message.capturedByInertia != null && message.hasOwnProperty("capturedByInertia"))
object.capturedByInertia = message.capturedByInertia;
if (message.name != null && message.hasOwnProperty("name"))
object.name = message.name;
if (message.displayName != null && message.hasOwnProperty("displayName"))
@@ -2291,6 +2383,7 @@ $root.protos = (function() {
* @interface IInputFrameUpsync
* @property {number|null} [inputFrameId] InputFrameUpsync inputFrameId
* @property {number|Long|null} [encoded] InputFrameUpsync encoded
* @property {number|null} [joinIndex] InputFrameUpsync joinIndex
*/
/**
@@ -2324,6 +2417,14 @@ $root.protos = (function() {
*/
InputFrameUpsync.prototype.encoded = $util.Long ? $util.Long.fromBits(0,0,true) : 0;
/**
* InputFrameUpsync joinIndex.
* @member {number} joinIndex
* @memberof protos.InputFrameUpsync
* @instance
*/
InputFrameUpsync.prototype.joinIndex = 0;
/**
* Creates a new InputFrameUpsync instance using the specified properties.
* @function create
@@ -2352,6 +2453,8 @@ $root.protos = (function() {
writer.uint32(/* id 1, wireType 0 =*/8).int32(message.inputFrameId);
if (message.encoded != null && Object.hasOwnProperty.call(message, "encoded"))
writer.uint32(/* id 2, wireType 0 =*/16).uint64(message.encoded);
if (message.joinIndex != null && Object.hasOwnProperty.call(message, "joinIndex"))
writer.uint32(/* id 3, wireType 0 =*/24).int32(message.joinIndex);
return writer;
};
@@ -2394,6 +2497,10 @@ $root.protos = (function() {
message.encoded = reader.uint64();
break;
}
case 3: {
message.joinIndex = reader.int32();
break;
}
default:
reader.skipType(tag & 7);
break;
@@ -2435,6 +2542,9 @@ $root.protos = (function() {
if (message.encoded != null && message.hasOwnProperty("encoded"))
if (!$util.isInteger(message.encoded) && !(message.encoded && $util.isInteger(message.encoded.low) && $util.isInteger(message.encoded.high)))
return "encoded: integer|Long expected";
if (message.joinIndex != null && message.hasOwnProperty("joinIndex"))
if (!$util.isInteger(message.joinIndex))
return "joinIndex: integer expected";
return null;
};
@@ -2461,6 +2571,8 @@ $root.protos = (function() {
message.encoded = object.encoded;
else if (typeof object.encoded === "object")
message.encoded = new $util.LongBits(object.encoded.low >>> 0, object.encoded.high >>> 0).toNumber(true);
if (object.joinIndex != null)
message.joinIndex = object.joinIndex | 0;
return message;
};
@@ -2484,6 +2596,7 @@ $root.protos = (function() {
object.encoded = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
} else
object.encoded = options.longs === String ? "0" : 0;
object.joinIndex = 0;
}
if (message.inputFrameId != null && message.hasOwnProperty("inputFrameId"))
object.inputFrameId = message.inputFrameId;
@@ -2492,6 +2605,8 @@ $root.protos = (function() {
object.encoded = options.longs === String ? String(message.encoded) : message.encoded;
else
object.encoded = options.longs === String ? $util.Long.prototype.toString.call(message.encoded) : options.longs === Number ? new $util.LongBits(message.encoded.low >>> 0, message.encoded.high >>> 0).toNumber(true) : message.encoded;
if (message.joinIndex != null && message.hasOwnProperty("joinIndex"))
object.joinIndex = message.joinIndex;
return object;
};
@@ -3444,6 +3559,7 @@ $root.protos = (function() {
* @property {protos.RoomDownsyncFrame|null} [rdf] WsResp rdf
* @property {Array.<protos.InputFrameDownsync>|null} [inputFrameDownsyncBatch] WsResp inputFrameDownsyncBatch
* @property {protos.BattleColliderInfo|null} [bciFrame] WsResp bciFrame
* @property {number|null} [peerJoinIndex] WsResp peerJoinIndex
*/
/**
@@ -3510,6 +3626,14 @@ $root.protos = (function() {
*/
WsResp.prototype.bciFrame = null;
/**
* WsResp peerJoinIndex.
* @member {number} peerJoinIndex
* @memberof protos.WsResp
* @instance
*/
WsResp.prototype.peerJoinIndex = 0;
/**
* Creates a new WsResp instance using the specified properties.
* @function create
@@ -3547,6 +3671,8 @@ $root.protos = (function() {
$root.protos.InputFrameDownsync.encode(message.inputFrameDownsyncBatch[i], writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim();
if (message.bciFrame != null && Object.hasOwnProperty.call(message, "bciFrame"))
$root.protos.BattleColliderInfo.encode(message.bciFrame, writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim();
if (message.peerJoinIndex != null && Object.hasOwnProperty.call(message, "peerJoinIndex"))
writer.uint32(/* id 7, wireType 0 =*/56).int32(message.peerJoinIndex);
return writer;
};
@@ -3607,6 +3733,10 @@ $root.protos = (function() {
message.bciFrame = $root.protos.BattleColliderInfo.decode(reader, reader.uint32());
break;
}
case 7: {
message.peerJoinIndex = reader.int32();
break;
}
default:
reader.skipType(tag & 7);
break;
@@ -3670,6 +3800,9 @@ $root.protos = (function() {
if (error)
return "bciFrame." + error;
}
if (message.peerJoinIndex != null && message.hasOwnProperty("peerJoinIndex"))
if (!$util.isInteger(message.peerJoinIndex))
return "peerJoinIndex: integer expected";
return null;
};
@@ -3711,6 +3844,8 @@ $root.protos = (function() {
throw TypeError(".protos.WsResp.bciFrame: object expected");
message.bciFrame = $root.protos.BattleColliderInfo.fromObject(object.bciFrame);
}
if (object.peerJoinIndex != null)
message.peerJoinIndex = object.peerJoinIndex | 0;
return message;
};
@@ -3735,6 +3870,7 @@ $root.protos = (function() {
object.act = 0;
object.rdf = null;
object.bciFrame = null;
object.peerJoinIndex = 0;
}
if (message.ret != null && message.hasOwnProperty("ret"))
object.ret = message.ret;
@@ -3751,6 +3887,8 @@ $root.protos = (function() {
}
if (message.bciFrame != null && message.hasOwnProperty("bciFrame"))
object.bciFrame = $root.protos.BattleColliderInfo.toObject(message.bciFrame, options);
if (message.peerJoinIndex != null && message.hasOwnProperty("peerJoinIndex"))
object.peerJoinIndex = message.peerJoinIndex;
return object;
};
@@ -3793,6 +3931,7 @@ $root.protos = (function() {
* @property {number|Long|null} [unconfirmedMask] InputsBufferSnapshot unconfirmedMask
* @property {Array.<protos.InputFrameDownsync>|null} [toSendInputFrameDownsyncs] InputsBufferSnapshot toSendInputFrameDownsyncs
* @property {boolean|null} [shouldForceResync] InputsBufferSnapshot shouldForceResync
* @property {number|null} [peerJoinIndex] InputsBufferSnapshot peerJoinIndex
*/
/**
@@ -3843,6 +3982,14 @@ $root.protos = (function() {
*/
InputsBufferSnapshot.prototype.shouldForceResync = false;
/**
* InputsBufferSnapshot peerJoinIndex.
* @member {number} peerJoinIndex
* @memberof protos.InputsBufferSnapshot
* @instance
*/
InputsBufferSnapshot.prototype.peerJoinIndex = 0;
/**
* Creates a new InputsBufferSnapshot instance using the specified properties.
* @function create
@@ -3876,6 +4023,8 @@ $root.protos = (function() {
$root.protos.InputFrameDownsync.encode(message.toSendInputFrameDownsyncs[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
if (message.shouldForceResync != null && Object.hasOwnProperty.call(message, "shouldForceResync"))
writer.uint32(/* id 4, wireType 0 =*/32).bool(message.shouldForceResync);
if (message.peerJoinIndex != null && Object.hasOwnProperty.call(message, "peerJoinIndex"))
writer.uint32(/* id 5, wireType 0 =*/40).int32(message.peerJoinIndex);
return writer;
};
@@ -3928,6 +4077,10 @@ $root.protos = (function() {
message.shouldForceResync = reader.bool();
break;
}
case 5: {
message.peerJoinIndex = reader.int32();
break;
}
default:
reader.skipType(tag & 7);
break;
@@ -3981,6 +4134,9 @@ $root.protos = (function() {
if (message.shouldForceResync != null && message.hasOwnProperty("shouldForceResync"))
if (typeof message.shouldForceResync !== "boolean")
return "shouldForceResync: boolean expected";
if (message.peerJoinIndex != null && message.hasOwnProperty("peerJoinIndex"))
if (!$util.isInteger(message.peerJoinIndex))
return "peerJoinIndex: integer expected";
return null;
};
@@ -4019,6 +4175,8 @@ $root.protos = (function() {
}
if (object.shouldForceResync != null)
message.shouldForceResync = Boolean(object.shouldForceResync);
if (object.peerJoinIndex != null)
message.peerJoinIndex = object.peerJoinIndex | 0;
return message;
};
@@ -4045,6 +4203,7 @@ $root.protos = (function() {
} else
object.unconfirmedMask = options.longs === String ? "0" : 0;
object.shouldForceResync = false;
object.peerJoinIndex = 0;
}
if (message.refRenderFrameId != null && message.hasOwnProperty("refRenderFrameId"))
object.refRenderFrameId = message.refRenderFrameId;
@@ -4060,6 +4219,8 @@ $root.protos = (function() {
}
if (message.shouldForceResync != null && message.hasOwnProperty("shouldForceResync"))
object.shouldForceResync = message.shouldForceResync;
if (message.peerJoinIndex != null && message.hasOwnProperty("peerJoinIndex"))
object.peerJoinIndex = message.peerJoinIndex;
return object;
};
@@ -4118,6 +4279,10 @@ $root.protos = (function() {
* @property {boolean|null} [blowUp] MeleeBullet blowUp
* @property {number|null} [teamId] MeleeBullet teamId
* @property {number|null} [bulletLocalId] MeleeBullet bulletLocalId
* @property {number|null} [speciesId] MeleeBullet speciesId
* @property {number|null} [explosionFrames] MeleeBullet explosionFrames
* @property {number|null} [blState] MeleeBullet blState
* @property {number|null} [framesInBlState] MeleeBullet framesInBlState
*/
/**
@@ -4295,6 +4460,38 @@ $root.protos = (function() {
*/
MeleeBullet.prototype.bulletLocalId = 0;
/**
* MeleeBullet speciesId.
* @member {number} speciesId
* @memberof protos.MeleeBullet
* @instance
*/
MeleeBullet.prototype.speciesId = 0;
/**
* MeleeBullet explosionFrames.
* @member {number} explosionFrames
* @memberof protos.MeleeBullet
* @instance
*/
MeleeBullet.prototype.explosionFrames = 0;
/**
* MeleeBullet blState.
* @member {number} blState
* @memberof protos.MeleeBullet
* @instance
*/
MeleeBullet.prototype.blState = 0;
/**
* MeleeBullet framesInBlState.
* @member {number} framesInBlState
* @memberof protos.MeleeBullet
* @instance
*/
MeleeBullet.prototype.framesInBlState = 0;
/**
* Creates a new MeleeBullet instance using the specified properties.
* @function create
@@ -4359,6 +4556,14 @@ $root.protos = (function() {
writer.uint32(/* id 19, wireType 0 =*/152).int32(message.teamId);
if (message.bulletLocalId != null && Object.hasOwnProperty.call(message, "bulletLocalId"))
writer.uint32(/* id 20, wireType 0 =*/160).int32(message.bulletLocalId);
if (message.speciesId != null && Object.hasOwnProperty.call(message, "speciesId"))
writer.uint32(/* id 21, wireType 0 =*/168).int32(message.speciesId);
if (message.explosionFrames != null && Object.hasOwnProperty.call(message, "explosionFrames"))
writer.uint32(/* id 22, wireType 0 =*/176).int32(message.explosionFrames);
if (message.blState != null && Object.hasOwnProperty.call(message, "blState"))
writer.uint32(/* id 23, wireType 0 =*/184).int32(message.blState);
if (message.framesInBlState != null && Object.hasOwnProperty.call(message, "framesInBlState"))
writer.uint32(/* id 24, wireType 0 =*/192).int32(message.framesInBlState);
return writer;
};
@@ -4473,6 +4678,22 @@ $root.protos = (function() {
message.bulletLocalId = reader.int32();
break;
}
case 21: {
message.speciesId = reader.int32();
break;
}
case 22: {
message.explosionFrames = reader.int32();
break;
}
case 23: {
message.blState = reader.int32();
break;
}
case 24: {
message.framesInBlState = reader.int32();
break;
}
default:
reader.skipType(tag & 7);
break;
@@ -4568,6 +4789,18 @@ $root.protos = (function() {
if (message.bulletLocalId != null && message.hasOwnProperty("bulletLocalId"))
if (!$util.isInteger(message.bulletLocalId))
return "bulletLocalId: integer expected";
if (message.speciesId != null && message.hasOwnProperty("speciesId"))
if (!$util.isInteger(message.speciesId))
return "speciesId: integer expected";
if (message.explosionFrames != null && message.hasOwnProperty("explosionFrames"))
if (!$util.isInteger(message.explosionFrames))
return "explosionFrames: integer expected";
if (message.blState != null && message.hasOwnProperty("blState"))
if (!$util.isInteger(message.blState))
return "blState: integer expected";
if (message.framesInBlState != null && message.hasOwnProperty("framesInBlState"))
if (!$util.isInteger(message.framesInBlState))
return "framesInBlState: integer expected";
return null;
};
@@ -4623,6 +4856,14 @@ $root.protos = (function() {
message.teamId = object.teamId | 0;
if (object.bulletLocalId != null)
message.bulletLocalId = object.bulletLocalId | 0;
if (object.speciesId != null)
message.speciesId = object.speciesId | 0;
if (object.explosionFrames != null)
message.explosionFrames = object.explosionFrames | 0;
if (object.blState != null)
message.blState = object.blState | 0;
if (object.framesInBlState != null)
message.framesInBlState = object.framesInBlState | 0;
return message;
};
@@ -4660,6 +4901,10 @@ $root.protos = (function() {
object.blowUp = false;
object.teamId = 0;
object.bulletLocalId = 0;
object.speciesId = 0;
object.explosionFrames = 0;
object.blState = 0;
object.framesInBlState = 0;
}
if (message.originatedRenderFrameId != null && message.hasOwnProperty("originatedRenderFrameId"))
object.originatedRenderFrameId = message.originatedRenderFrameId;
@@ -4701,6 +4946,14 @@ $root.protos = (function() {
object.teamId = message.teamId;
if (message.bulletLocalId != null && message.hasOwnProperty("bulletLocalId"))
object.bulletLocalId = message.bulletLocalId;
if (message.speciesId != null && message.hasOwnProperty("speciesId"))
object.speciesId = message.speciesId;
if (message.explosionFrames != null && message.hasOwnProperty("explosionFrames"))
object.explosionFrames = message.explosionFrames;
if (message.blState != null && message.hasOwnProperty("blState"))
object.blState = message.blState;
if (message.framesInBlState != null && message.hasOwnProperty("framesInBlState"))
object.framesInBlState = message.framesInBlState;
return object;
};
@@ -4759,6 +5012,10 @@ $root.protos = (function() {
* @property {boolean|null} [blowUp] FireballBullet blowUp
* @property {number|null} [teamId] FireballBullet teamId
* @property {number|null} [bulletLocalId] FireballBullet bulletLocalId
* @property {number|null} [speciesId] FireballBullet speciesId
* @property {number|null} [explosionFrames] FireballBullet explosionFrames
* @property {number|null} [blState] FireballBullet blState
* @property {number|null} [framesInBlState] FireballBullet framesInBlState
* @property {number|null} [virtualGridX] FireballBullet virtualGridX
* @property {number|null} [virtualGridY] FireballBullet virtualGridY
* @property {number|null} [dirX] FireballBullet dirX
@@ -4943,6 +5200,38 @@ $root.protos = (function() {
*/
FireballBullet.prototype.bulletLocalId = 0;
/**
* FireballBullet speciesId.
* @member {number} speciesId
* @memberof protos.FireballBullet
* @instance
*/
FireballBullet.prototype.speciesId = 0;
/**
* FireballBullet explosionFrames.
* @member {number} explosionFrames
* @memberof protos.FireballBullet
* @instance
*/
FireballBullet.prototype.explosionFrames = 0;
/**
* FireballBullet blState.
* @member {number} blState
* @memberof protos.FireballBullet
* @instance
*/
FireballBullet.prototype.blState = 0;
/**
* FireballBullet framesInBlState.
* @member {number} framesInBlState
* @memberof protos.FireballBullet
* @instance
*/
FireballBullet.prototype.framesInBlState = 0;
/**
* FireballBullet virtualGridX.
* @member {number} virtualGridX
@@ -5063,6 +5352,14 @@ $root.protos = (function() {
writer.uint32(/* id 19, wireType 0 =*/152).int32(message.teamId);
if (message.bulletLocalId != null && Object.hasOwnProperty.call(message, "bulletLocalId"))
writer.uint32(/* id 20, wireType 0 =*/160).int32(message.bulletLocalId);
if (message.speciesId != null && Object.hasOwnProperty.call(message, "speciesId"))
writer.uint32(/* id 21, wireType 0 =*/168).int32(message.speciesId);
if (message.explosionFrames != null && Object.hasOwnProperty.call(message, "explosionFrames"))
writer.uint32(/* id 22, wireType 0 =*/176).int32(message.explosionFrames);
if (message.blState != null && Object.hasOwnProperty.call(message, "blState"))
writer.uint32(/* id 23, wireType 0 =*/184).int32(message.blState);
if (message.framesInBlState != null && Object.hasOwnProperty.call(message, "framesInBlState"))
writer.uint32(/* id 24, wireType 0 =*/192).int32(message.framesInBlState);
if (message.virtualGridX != null && Object.hasOwnProperty.call(message, "virtualGridX"))
writer.uint32(/* id 999, wireType 0 =*/7992).int32(message.virtualGridX);
if (message.virtualGridY != null && Object.hasOwnProperty.call(message, "virtualGridY"))
@@ -5191,6 +5488,22 @@ $root.protos = (function() {
message.bulletLocalId = reader.int32();
break;
}
case 21: {
message.speciesId = reader.int32();
break;
}
case 22: {
message.explosionFrames = reader.int32();
break;
}
case 23: {
message.blState = reader.int32();
break;
}
case 24: {
message.framesInBlState = reader.int32();
break;
}
case 999: {
message.virtualGridX = reader.int32();
break;
@@ -5314,6 +5627,18 @@ $root.protos = (function() {
if (message.bulletLocalId != null && message.hasOwnProperty("bulletLocalId"))
if (!$util.isInteger(message.bulletLocalId))
return "bulletLocalId: integer expected";
if (message.speciesId != null && message.hasOwnProperty("speciesId"))
if (!$util.isInteger(message.speciesId))
return "speciesId: integer expected";
if (message.explosionFrames != null && message.hasOwnProperty("explosionFrames"))
if (!$util.isInteger(message.explosionFrames))
return "explosionFrames: integer expected";
if (message.blState != null && message.hasOwnProperty("blState"))
if (!$util.isInteger(message.blState))
return "blState: integer expected";
if (message.framesInBlState != null && message.hasOwnProperty("framesInBlState"))
if (!$util.isInteger(message.framesInBlState))
return "framesInBlState: integer expected";
if (message.virtualGridX != null && message.hasOwnProperty("virtualGridX"))
if (!$util.isInteger(message.virtualGridX))
return "virtualGridX: integer expected";
@@ -5390,6 +5715,14 @@ $root.protos = (function() {
message.teamId = object.teamId | 0;
if (object.bulletLocalId != null)
message.bulletLocalId = object.bulletLocalId | 0;
if (object.speciesId != null)
message.speciesId = object.speciesId | 0;
if (object.explosionFrames != null)
message.explosionFrames = object.explosionFrames | 0;
if (object.blState != null)
message.blState = object.blState | 0;
if (object.framesInBlState != null)
message.framesInBlState = object.framesInBlState | 0;
if (object.virtualGridX != null)
message.virtualGridX = object.virtualGridX | 0;
if (object.virtualGridY != null)
@@ -5441,6 +5774,10 @@ $root.protos = (function() {
object.blowUp = false;
object.teamId = 0;
object.bulletLocalId = 0;
object.speciesId = 0;
object.explosionFrames = 0;
object.blState = 0;
object.framesInBlState = 0;
object.virtualGridX = 0;
object.virtualGridY = 0;
object.dirX = 0;
@@ -5489,6 +5826,14 @@ $root.protos = (function() {
object.teamId = message.teamId;
if (message.bulletLocalId != null && message.hasOwnProperty("bulletLocalId"))
object.bulletLocalId = message.bulletLocalId;
if (message.speciesId != null && message.hasOwnProperty("speciesId"))
object.speciesId = message.speciesId;
if (message.explosionFrames != null && message.hasOwnProperty("explosionFrames"))
object.explosionFrames = message.explosionFrames;
if (message.blState != null && message.hasOwnProperty("blState"))
object.blState = message.blState;
if (message.framesInBlState != null && message.hasOwnProperty("framesInBlState"))
object.framesInBlState = message.framesInBlState;
if (message.virtualGridX != null && message.hasOwnProperty("virtualGridX"))
object.virtualGridX = message.virtualGridX;
if (message.virtualGridY != null && message.hasOwnProperty("virtualGridY"))

View File

@@ -38,7 +38,7 @@
"orientation": "portrait"
},
"startScene": "2ff474d9-0c9e-4fe3-87ec-fbff7cae85b4",
"title": "TreasureHunterX",
"title": "DelayNoMore",
"webOrientation": "portrait",
"wechatgame": {
"REMOTE_SERVER_ROOT": "https://bgmoba.lokcol.com/static/",

View File

@@ -68,7 +68,7 @@
"shelter_z_reducer",
"shelter"
],
"last-module-event-record-time": 1673325961305,
"last-module-event-record-time": 1673930863015,
"simulator-orientation": false,
"simulator-resolution": {
"height": 640,

View File

@@ -6,16 +6,22 @@ all: help
GOPROXY=https://goproxy.io
serve:
gopherjs clean
gopherjs serve $(PROJECTNAME)
build:
gopherjs build $(PROJECTNAME)
rm ../frontend/assets/plugin_scripts/jsexport.js && mv ./jsexport.js ../frontend/assets/plugin_scripts/jsexport.js
clean:
gopherjs clean
rm -f ../frontend/assets/plugin_scripts/jsexport.js
#rm -f ../frontend/assets/plugin_scripts/jsexport.js.map
build-min:
build: clean
gopherjs build $(PROJECTNAME)
mv ./jsexport.js ../frontend/assets/plugin_scripts/
#mv ./jsexport.js.map ../frontend/assets/plugin_scripts/
build-min: clean
gopherjs build -m $(PROJECTNAME)
rm ../frontend/assets/plugin_scripts/jsexport.js && mv ./jsexport.js ../frontend/assets/plugin_scripts/jsexport.js
mv ./jsexport.js ../frontend/assets/plugin_scripts/
#mv ./jsexport.js.map ../frontend/assets/plugin_scripts/
.PHONY: help

View File

@@ -1,6 +1,7 @@
package battle
import (
//"fmt"
"math"
"resolv"
)
@@ -15,7 +16,7 @@ const (
PATTERN_ID_UNABLE_TO_OP = -2
PATTERN_ID_NO_OP = -1
WORLD_TO_VIRTUAL_GRID_RATIO = float64(100)
WORLD_TO_VIRTUAL_GRID_RATIO = float64(100.0)
VIRTUAL_GRID_TO_WORLD_RATIO = float64(1.0) / WORLD_TO_VIRTUAL_GRID_RATIO
GRAVITY_X = int32(0)
@@ -29,6 +30,7 @@ const (
SNAP_INTO_PLATFORM_OVERLAP = float64(0.1)
SNAP_INTO_PLATFORM_THRESHOLD = float64(0.5)
VERTICAL_PLATFORM_THRESHOLD = float64(0.9)
NO_SKILL = -1
NO_SKILL_HIT = -1
@@ -49,6 +51,12 @@ var DIRECTION_DECODER = [][]int32{
{-1, +1},
}
const (
BULLET_STARTUP = int32(0)
BULLET_ACTIVE = int32(1)
BULLET_EXPLODING = int32(2)
)
const (
ATK_CHARACTER_STATE_IDLE1 = int32(0)
ATK_CHARACTER_STATE_WALKING = int32(1)
@@ -65,6 +73,12 @@ const (
ATK_CHARACTER_STATE_ATK2 = int32(11)
ATK_CHARACTER_STATE_ATK3 = int32(12)
ATK_CHARACTER_STATE_ATK4 = int32(13)
ATK_CHARACTER_STATE_ATK5 = int32(14)
ATK_CHARACTER_STATE_DASHING = int32(15)
ATK_CHARACTER_STATE_ONWALL = int32(16)
ATK_CHARACTER_STATE_TURNAROUND = int32(17)
)
var inAirSet = map[int32]bool{
@@ -73,6 +87,7 @@ var inAirSet = map[int32]bool{
ATK_CHARACTER_STATE_INAIR_ATK1: true,
ATK_CHARACTER_STATE_INAIR_ATKED1: true,
ATK_CHARACTER_STATE_BLOWN_UP1: true,
ATK_CHARACTER_STATE_ONWALL: true,
}
var noOpSet = map[int32]bool{
@@ -101,6 +116,13 @@ var nonAttackingSet = map[int32]bool{
ATK_CHARACTER_STATE_GET_UP1: true,
}
func intAbs(x int32) int32 {
if x < 0 {
return -x
}
return x
}
func ShouldPrefabInputFrameDownsync(prevRenderFrameId int32, renderFrameId int32) (bool, int32) {
for i := prevRenderFrameId + 1; i <= renderFrameId; i++ {
if (0 <= i) && (0 == (i & ((1 << INPUT_SCALE_FRAMES) - 1))) {
@@ -154,7 +176,7 @@ type SatResult struct {
Axis resolv.Vector
}
func CalcPushbacks(oldDx, oldDy float64, playerShape, barrierShape *resolv.ConvexPolygon) (bool, float64, float64, *SatResult) {
func calcPushbacks(oldDx, oldDy float64, playerShape, barrierShape *resolv.ConvexPolygon) (bool, float64, float64, *SatResult) {
origX, origY := playerShape.Position()
defer func() {
playerShape.SetPosition(origX, origY)
@@ -206,6 +228,34 @@ func isPolygonPairOverlapped(a, b *resolv.ConvexPolygon, result *SatResult) bool
return true
}
func IsMeleeBulletActive(meleeBullet *MeleeBullet, currRenderFrame *RoomDownsyncFrame) bool {
if BULLET_EXPLODING == meleeBullet.BlState {
return false
}
return (meleeBullet.BattleAttr.OriginatedRenderFrameId+meleeBullet.Bullet.StartupFrames <= currRenderFrame.Id) && (meleeBullet.BattleAttr.OriginatedRenderFrameId+meleeBullet.Bullet.StartupFrames+meleeBullet.Bullet.ActiveFrames > currRenderFrame.Id)
}
func IsMeleeBulletAlive(meleeBullet *MeleeBullet, currRenderFrame *RoomDownsyncFrame) bool {
if BULLET_EXPLODING == meleeBullet.BlState {
return meleeBullet.FramesInBlState < meleeBullet.Bullet.ExplosionFrames
}
return (meleeBullet.BattleAttr.OriginatedRenderFrameId+meleeBullet.Bullet.StartupFrames+meleeBullet.Bullet.ActiveFrames > currRenderFrame.Id)
}
func IsFireballBulletActive(fireballBullet *FireballBullet, currRenderFrame *RoomDownsyncFrame) bool {
if BULLET_EXPLODING == fireballBullet.BlState {
return false
}
return (fireballBullet.BattleAttr.OriginatedRenderFrameId+fireballBullet.Bullet.StartupFrames < currRenderFrame.Id) && (fireballBullet.BattleAttr.OriginatedRenderFrameId+fireballBullet.Bullet.StartupFrames+fireballBullet.Bullet.ActiveFrames > currRenderFrame.Id)
}
func IsFireballBulletAlive(fireballBullet *FireballBullet, currRenderFrame *RoomDownsyncFrame) bool {
if BULLET_EXPLODING == fireballBullet.BlState {
return fireballBullet.FramesInBlState < fireballBullet.Bullet.ExplosionFrames
}
return (fireballBullet.BattleAttr.OriginatedRenderFrameId+fireballBullet.Bullet.StartupFrames+fireballBullet.Bullet.ActiveFrames > currRenderFrame.Id)
}
func isPolygonPairSeparatedByDir(a, b *resolv.ConvexPolygon, e resolv.Vector, result *SatResult) bool {
/*
[WARNING] This function is deliberately made private, it shouldn't be used alone (i.e. not along the norms of a polygon), otherwise the pushbacks calculated would be meaningless.
@@ -315,8 +365,8 @@ func isPolygonPairSeparatedByDir(a, b *resolv.ConvexPolygon, e resolv.Vector, re
func WorldToVirtualGridPos(wx, wy float64) (int32, int32) {
// [WARNING] Introduces loss of precision!
// In JavaScript floating numbers suffer from seemingly non-deterministic arithmetics, and even if certain libs solved this issue by approaches such as fixed-point-number, they might not be used in other libs -- e.g. the "collision libs" we're interested in -- thus couldn't kill all pains.
var virtualGridX int32 = int32(math.Floor(wx * WORLD_TO_VIRTUAL_GRID_RATIO))
var virtualGridY int32 = int32(math.Floor(wy * WORLD_TO_VIRTUAL_GRID_RATIO))
var virtualGridX int32 = int32(math.Round(wx * WORLD_TO_VIRTUAL_GRID_RATIO))
var virtualGridY int32 = int32(math.Round(wy * WORLD_TO_VIRTUAL_GRID_RATIO))
return virtualGridX, virtualGridY
}
@@ -345,9 +395,25 @@ func VirtualGridToPolygonColliderBLPos(vx, vy int32, halfBoundingW, halfBounding
return WorldToPolygonColliderBLPos(wx, wy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY)
}
func calcHardPushbacksNorms(joinIndex int32, playerCollider *resolv.Object, playerShape *resolv.ConvexPolygon, snapIntoPlatformOverlap float64, pEffPushback *Vec2D) *[]Vec2D {
func calcHardPushbacksNorms(joinIndex int32, currPlayerDownsync, thatPlayerInNextFrame *PlayerDownsync, playerCollider *resolv.Object, playerShape *resolv.ConvexPolygon, snapIntoPlatformOverlap float64, pEffPushback *Vec2D) *[]Vec2D {
ret := make([]Vec2D, 0, 10) // no one would simultaneously have more than 5 hardPushbacks
collision := playerCollider.Check(0, 0)
virtualGripToWall := float64(0)
if ATK_CHARACTER_STATE_ONWALL == currPlayerDownsync.CharacterState && 0 == thatPlayerInNextFrame.VelX && currPlayerDownsync.DirX == thatPlayerInNextFrame.DirX {
/*
I'm not sure whether this is a bug of "resolv_tailored" (maybe due to my changes), on the x-axis a playerCollider whose right edge reaches "1680.1" is not deemed collided with a side wall whose left edge is "1680.0", while the same extent of intersection is OK in y-axis.
The workaround here is to grant a "virtualGripToWall" in x-axis to guarantee that if
- "currPlayerDownsync" is on wall, and
- "thatPlayerInNextFrame.VelX" is 0 (i.e. no proactive move against the wall), and
- there's no change in player facing direction
*/
xfac := float64(1)
if 0 > thatPlayerInNextFrame.DirX {
xfac = -xfac
}
virtualGripToWall = xfac * float64(currPlayerDownsync.Speed) * VIRTUAL_GRID_TO_WORLD_RATIO
}
collision := playerCollider.Check(virtualGripToWall, 0)
if nil == collision {
return &ret
}
@@ -357,8 +423,7 @@ func calcHardPushbacksNorms(joinIndex int32, playerCollider *resolv.Object, play
for _, obj := range collision.Objects {
isBarrier := false
switch obj.Data.(type) {
case *PlayerDownsync:
case *MeleeBullet, *FireballBullet:
case *PlayerDownsync, *MeleeBullet, *FireballBullet:
default:
// By default it's a regular barrier, even if data is nil, note that Golang syntax of switch-case is kind of confusing, this "default" condition is met only if "!*PlayerDownsync && !*MeleeBullet && !*FireballBullet".
isBarrier = true
@@ -368,7 +433,7 @@ func calcHardPushbacksNorms(joinIndex int32, playerCollider *resolv.Object, play
continue
}
barrierShape := obj.Shape.(*resolv.ConvexPolygon)
overlapped, pushbackX, pushbackY, overlapResult := CalcPushbacks(0, 0, playerShape, barrierShape)
overlapped, pushbackX, pushbackY, overlapResult := calcPushbacks(0, 0, playerShape, barrierShape)
if !overlapped {
continue
}
@@ -383,7 +448,7 @@ func calcHardPushbacksNorms(joinIndex int32, playerCollider *resolv.Object, play
return &ret
}
func deriveOpPattern(currPlayerDownsync, thatPlayerInNextFrame *PlayerDownsync, currRenderFrame *RoomDownsyncFrame, inputsBuffer *RingBuffer) (int, bool, int32, int32) {
func deriveOpPattern(currPlayerDownsync, thatPlayerInNextFrame *PlayerDownsync, currRenderFrame *RoomDownsyncFrame, chConfig *CharacterConfig, inputsBuffer *RingBuffer) (int, bool, int32, int32) {
// returns (patternId, jumpedOrNot, effectiveDx, effectiveDy)
delayedInputFrameId := ConvertToDelayedInputFrameId(currRenderFrame.Id)
delayedInputFrameIdForPrevRdf := ConvertToDelayedInputFrameId(currRenderFrame.Id - 1)
@@ -413,19 +478,40 @@ func deriveOpPattern(currPlayerDownsync, thatPlayerInNextFrame *PlayerDownsync,
prevBtnBLevel = prevDecodedInput.BtnBLevel
}
// Jumping is partially allowed within "CapturedByInertia", but moving is only allowed when "0 == FramesToRecover" (constrained later in "ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame")
if 0 == currPlayerDownsync.FramesToRecover {
// Jumping and moving are only allowed here
effDx, effDy = decodedInput.Dx, decodedInput.Dy
}
patternId := PATTERN_ID_NO_OP
canJumpWithinInertia := currPlayerDownsync.CapturedByInertia && ((chConfig.InertiaFramesToRecover >> 1) > currPlayerDownsync.FramesToRecover)
if 0 == currPlayerDownsync.FramesToRecover || canJumpWithinInertia {
if decodedInput.BtnBLevel > prevBtnBLevel {
if _, existent := inAirSet[currPlayerDownsync.CharacterState]; !existent {
if chConfig.DashingEnabled && 0 > decodedInput.Dy {
// Checking "DashingEnabled" here to allow jumping when dashing-disabled players pressed "DOWN + BtnB"
patternId = 5
} else if _, existent := inAirSet[currPlayerDownsync.CharacterState]; !existent {
jumpedOrNot = true
} else if ATK_CHARACTER_STATE_ONWALL == currPlayerDownsync.CharacterState {
jumpedOrNot = true
}
}
}
patternId := PATTERN_ID_NO_OP
if decodedInput.BtnALevel > prevBtnALevel {
patternId = 1
if PATTERN_ID_NO_OP == patternId {
if 0 < decodedInput.BtnALevel {
if decodedInput.BtnALevel > prevBtnALevel {
if 0 > decodedInput.Dy {
patternId = 3
} else if 0 < decodedInput.Dy {
patternId = 2
} else {
patternId = 1
}
} else {
patternId = 4 // Holding
}
}
}
return patternId, jumpedOrNot, effDx, effDy
@@ -439,28 +525,32 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
// Make a copy first
for i, currPlayerDownsync := range currRenderFrame.PlayersArr {
nextRenderFramePlayers[i] = &PlayerDownsync{
Id: currPlayerDownsync.Id,
VirtualGridX: currPlayerDownsync.VirtualGridX,
VirtualGridY: currPlayerDownsync.VirtualGridY,
DirX: currPlayerDownsync.DirX,
DirY: currPlayerDownsync.DirY,
VelX: currPlayerDownsync.VelX,
VelY: currPlayerDownsync.VelY,
CharacterState: currPlayerDownsync.CharacterState,
InAir: true,
Speed: currPlayerDownsync.Speed,
BattleState: currPlayerDownsync.BattleState,
Score: currPlayerDownsync.Score,
Removed: currPlayerDownsync.Removed,
JoinIndex: currPlayerDownsync.JoinIndex,
Hp: currPlayerDownsync.Hp,
MaxHp: currPlayerDownsync.MaxHp,
FramesToRecover: currPlayerDownsync.FramesToRecover - 1,
FramesInChState: currPlayerDownsync.FramesInChState + 1,
ActiveSkillId: currPlayerDownsync.ActiveSkillId,
ActiveSkillHit: currPlayerDownsync.ActiveSkillHit,
FramesInvinsible: currPlayerDownsync.FramesInvinsible - 1,
ColliderRadius: currPlayerDownsync.ColliderRadius,
Id: currPlayerDownsync.Id,
VirtualGridX: currPlayerDownsync.VirtualGridX,
VirtualGridY: currPlayerDownsync.VirtualGridY,
DirX: currPlayerDownsync.DirX,
DirY: currPlayerDownsync.DirY,
VelX: currPlayerDownsync.VelX,
VelY: currPlayerDownsync.VelY,
CharacterState: currPlayerDownsync.CharacterState,
InAir: true,
OnWall: false,
Speed: currPlayerDownsync.Speed,
BattleState: currPlayerDownsync.BattleState,
Score: currPlayerDownsync.Score,
Removed: currPlayerDownsync.Removed,
JoinIndex: currPlayerDownsync.JoinIndex,
Hp: currPlayerDownsync.Hp,
MaxHp: currPlayerDownsync.MaxHp,
FramesToRecover: currPlayerDownsync.FramesToRecover - 1,
FramesInChState: currPlayerDownsync.FramesInChState + 1,
ActiveSkillId: currPlayerDownsync.ActiveSkillId,
ActiveSkillHit: currPlayerDownsync.ActiveSkillHit,
FramesInvinsible: currPlayerDownsync.FramesInvinsible - 1,
ColliderRadius: currPlayerDownsync.ColliderRadius,
OnWallNormX: currPlayerDownsync.OnWallNormX,
OnWallNormY: currPlayerDownsync.OnWallNormY,
CapturedByInertia: currPlayerDownsync.CapturedByInertia,
}
if nextRenderFramePlayers[i].FramesToRecover < 0 {
nextRenderFramePlayers[i].FramesToRecover = 0
@@ -479,15 +569,11 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
bulletLocalId := currRenderFrame.BulletLocalIdCounter
// 1. Process player inputs
for i, currPlayerDownsync := range currRenderFrame.PlayersArr {
jumpedOrNotList[i] = false
chConfig := chConfigsOrderedByJoinIndex[i]
thatPlayerInNextFrame := nextRenderFramePlayers[i]
patternId, jumpedOrNot, effDx, effDy := deriveOpPattern(currPlayerDownsync, thatPlayerInNextFrame, currRenderFrame, inputsBuffer)
patternId, jumpedOrNot, effDx, effDy := deriveOpPattern(currPlayerDownsync, thatPlayerInNextFrame, currRenderFrame, chConfig, inputsBuffer)
if jumpedOrNot {
thatPlayerInNextFrame.VelY = int32(chConfig.JumpingInitVelY)
jumpedOrNotList[i] = true
}
jumpedOrNotList[i] = jumpedOrNot
joinIndex := currPlayerDownsync.JoinIndex
skillId := chConfig.SkillMapper(patternId, currPlayerDownsync)
if skillConfig, existent := skills[skillId]; existent {
@@ -504,40 +590,48 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
switch v := skillConfig.Hits[thatPlayerInNextFrame.ActiveSkillHit].(type) {
case *MeleeBullet:
var newBullet MeleeBullet = *v // Copied primitive fields into an onstack variable
newBullet.BulletLocalId = bulletLocalId
bulletLocalId++
newBullet.OriginatedRenderFrameId = currRenderFrame.Id
newBullet.OffenderJoinIndex = joinIndex
nextRenderFrameMeleeBullets = append(nextRenderFrameMeleeBullets, &newBullet)
if NO_LOCK_VEL != v.SelfLockVelX {
hasLockVel = true
thatPlayerInNextFrame.VelX = xfac * v.SelfLockVelX
newBullet.BattleAttr = &BulletBattleAttr{
BulletLocalId: bulletLocalId,
OriginatedRenderFrameId: currRenderFrame.Id,
OffenderJoinIndex: joinIndex,
TeamId: currPlayerDownsync.BulletTeamId,
}
if NO_LOCK_VEL != v.SelfLockVelY {
bulletLocalId++
newBullet.BlState = BULLET_STARTUP
nextRenderFrameMeleeBullets = append(nextRenderFrameMeleeBullets, &newBullet)
if NO_LOCK_VEL != v.Bullet.SelfLockVelX {
hasLockVel = true
thatPlayerInNextFrame.VelY = v.SelfLockVelY
thatPlayerInNextFrame.VelX = xfac * v.Bullet.SelfLockVelX
}
if NO_LOCK_VEL != v.Bullet.SelfLockVelY {
hasLockVel = true
thatPlayerInNextFrame.VelY = v.Bullet.SelfLockVelY
}
case *FireballBullet:
var newBullet FireballBullet = *v // Copied primitive fields into an onstack variable
newBullet.BulletLocalId = bulletLocalId
bulletLocalId++
xfac := int32(1)
if 0 > thatPlayerInNextFrame.DirX {
xfac = -xfac
newBullet.BattleAttr = &BulletBattleAttr{
BulletLocalId: bulletLocalId,
OriginatedRenderFrameId: currRenderFrame.Id,
OffenderJoinIndex: joinIndex,
TeamId: currPlayerDownsync.BulletTeamId,
}
newBullet.VirtualGridX, newBullet.VirtualGridY = currPlayerDownsync.VirtualGridX+xfac*newBullet.HitboxOffsetX, currPlayerDownsync.VirtualGridY
newBullet.OriginatedRenderFrameId = currRenderFrame.Id
newBullet.OffenderJoinIndex = joinIndex
bulletLocalId++
newBullet.VirtualGridX, newBullet.VirtualGridY = currPlayerDownsync.VirtualGridX+xfac*newBullet.Bullet.HitboxOffsetX, currPlayerDownsync.VirtualGridY+newBullet.Bullet.HitboxOffsetY
newBullet.DirX = xfac
newBullet.DirY = 0
newBullet.VelX = newBullet.Speed * xfac
newBullet.VelY = 0
newBullet.BlState = BULLET_STARTUP
nextRenderFrameFireballBullets = append(nextRenderFrameFireballBullets, &newBullet)
if NO_LOCK_VEL != v.SelfLockVelX {
//fmt.Printf("Created new fireball @currRenderFrame.Id=%d, %p, bulletLocalId=%d, virtualGridX=%d, virtualGridY=%d, offenderVpos=(%d,%d)\n", currRenderFrame.Id, &newBullet, bulletLocalId, newBullet.VirtualGridX, newBullet.VirtualGridY, currPlayerDownsync.VirtualGridX, currPlayerDownsync.VirtualGridY)
if NO_LOCK_VEL != v.Bullet.SelfLockVelX {
hasLockVel = true
thatPlayerInNextFrame.VelX = xfac * v.SelfLockVelX
thatPlayerInNextFrame.VelX = xfac * v.Bullet.SelfLockVelX
}
if NO_LOCK_VEL != v.SelfLockVelY {
if NO_LOCK_VEL != v.Bullet.SelfLockVelY {
hasLockVel = true
thatPlayerInNextFrame.VelY = v.SelfLockVelY
thatPlayerInNextFrame.VelY = v.Bullet.SelfLockVelY
}
}
@@ -549,14 +643,59 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
}
if 0 == currPlayerDownsync.FramesToRecover {
if 0 != effDx || 0 != effDy {
thatPlayerInNextFrame.DirX, thatPlayerInNextFrame.DirY = effDx, effDy
thatPlayerInNextFrame.VelX = effDx * currPlayerDownsync.Speed
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_WALKING
} else {
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_IDLE1
thatPlayerInNextFrame.VelX = 0
prevCapturedByInertia := currPlayerDownsync.CapturedByInertia
isWallJumping := (currPlayerDownsync.Speed < intAbs(currPlayerDownsync.VelX))
/*
if isWallJumping {
fmt.Printf("joinIndex=%d is wall jumping\n{renderFrame.id: %d, currPlayerDownsync.Speed: %d, currPlayerDownsync.VelX: %d}\n", currPlayerDownsync.JoinIndex, currRenderFrame.Id, currPlayerDownsync.Speed, currPlayerDownsync.VelX)
}
*/
alignedWithInertia := true
exactTurningAround := false
if 0 == effDx && 0 != thatPlayerInNextFrame.VelX {
alignedWithInertia = false
} else if 0 != effDx && 0 == thatPlayerInNextFrame.VelX {
alignedWithInertia = false
} else if 0 > effDx*thatPlayerInNextFrame.VelX {
alignedWithInertia = false
exactTurningAround = true
}
if !jumpedOrNot && !isWallJumping && !prevCapturedByInertia && !alignedWithInertia {
/*
[WARNING] A "turn-around", or in more generic direction schema a "change in direction" is a hurdle for our current "prediction+rollback" approach, yet applying a "FramesToRecover" for "turn-around" can alleviate the graphical inconsistence to a huge extent! For better operational experience, this is intentionally NOT APPLIED TO WALL JUMPING!
When "false == alignedWithInertia", we're GUARANTEED TO BE WRONG AT INPUT PREDICTION ON THE FRONTEND, but we COULD STILL BE RIGHT AT POSITION PREDICTION WITHIN "InertiaFramesToRecover" -- which together with "INPUT_DELAY_FRAMES" grants the frontend a big chance to be graphically consistent even upon wrong prediction!
*/
//fmt.Printf("joinIndex=%d is not wall jumping and not aligned w/ inertia\n{renderFrame.id: %d, effDx: %d, thatPlayerInNextFrame.VelX: %d}\n", currPlayerDownsync.JoinIndex, currRenderFrame.Id, effDx, thatPlayerInNextFrame.VelX)
thatPlayerInNextFrame.CapturedByInertia = true
thatPlayerInNextFrame.FramesToRecover = chConfig.InertiaFramesToRecover
if exactTurningAround {
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_TURNAROUND
}
} else {
thatPlayerInNextFrame.CapturedByInertia = false
if 0 != effDx {
xfac := int32(1)
if 0 > effDx {
xfac = -xfac
}
thatPlayerInNextFrame.DirX = effDx
thatPlayerInNextFrame.DirY = effDy
if isWallJumping {
//fmt.Printf("joinIndex=%d is controlling while wall jumping\n{renderFrame.id: %d, currPlayerDownsync.Speed: %d, currPlayerDownsync.VelX: %d, effDx: %d}\n", currPlayerDownsync.JoinIndex, currRenderFrame.Id, currPlayerDownsync.Speed, currPlayerDownsync.VelX, effDx)
thatPlayerInNextFrame.VelX = xfac * intAbs(currPlayerDownsync.VelX)
} else {
thatPlayerInNextFrame.VelX = xfac * currPlayerDownsync.Speed
}
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_WALKING
} else {
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_IDLE1
thatPlayerInNextFrame.VelX = 0
}
}
}
}
@@ -565,12 +704,31 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
for i, currPlayerDownsync := range currRenderFrame.PlayersArr {
joinIndex := currPlayerDownsync.JoinIndex
effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y = float64(0), float64(0)
thatPlayerInNextFrame := nextRenderFramePlayers[i]
chConfig := chConfigsOrderedByJoinIndex[i]
// Reset playerCollider position from the "virtual grid position"
newVx, newVy := currPlayerDownsync.VirtualGridX+currPlayerDownsync.VelX, currPlayerDownsync.VirtualGridY+currPlayerDownsync.VelY
if jumpedOrNotList[i] {
newVy += chConfig.JumpingInitVelY // Immediately gets out of any snapping
// We haven't proceeded with "OnWall" calculation for "thatPlayerInNextFrame", thus use "currPlayerDownsync.OnWall" for checking
if ATK_CHARACTER_STATE_ONWALL == currPlayerDownsync.CharacterState {
if 0 < currPlayerDownsync.VelX*currPlayerDownsync.OnWallNormX {
newVx -= currPlayerDownsync.VelX // Cancel the alleged horizontal movement pointing to same direction of wall inward norm first
}
xfac := int32(-1)
if 0 > currPlayerDownsync.OnWallNormX {
// Always jump to the opposite direction of wall inward norm
xfac = -xfac
}
newVx += xfac * chConfig.WallJumpingInitVelX
newVy += chConfig.WallJumpingInitVelY
thatPlayerInNextFrame.VelX = int32(xfac * chConfig.WallJumpingInitVelX)
thatPlayerInNextFrame.VelY = int32(chConfig.WallJumpingInitVelY)
thatPlayerInNextFrame.FramesToRecover = chConfig.WallJumpingFramesToRecover
} else {
thatPlayerInNextFrame.VelY = int32(chConfig.JumpingInitVelY)
newVy += chConfig.JumpingInitVelY // Immediately gets out of any snapping
}
}
wx, wy := VirtualGridToWorldPos(newVx, newVy)
@@ -578,7 +736,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
switch currPlayerDownsync.CharacterState {
case ATK_CHARACTER_STATE_LAY_DOWN1:
colliderWidth, colliderHeight = currPlayerDownsync.ColliderRadius*4, currPlayerDownsync.ColliderRadius*2
case ATK_CHARACTER_STATE_BLOWN_UP1, ATK_CHARACTER_STATE_INAIR_IDLE1_NO_JUMP, ATK_CHARACTER_STATE_INAIR_IDLE1_BY_JUMP:
case ATK_CHARACTER_STATE_BLOWN_UP1, ATK_CHARACTER_STATE_INAIR_IDLE1_NO_JUMP, ATK_CHARACTER_STATE_INAIR_IDLE1_BY_JUMP, ATK_CHARACTER_STATE_ONWALL:
colliderWidth, colliderHeight = currPlayerDownsync.ColliderRadius*2, currPlayerDownsync.ColliderRadius*2
}
@@ -590,41 +748,80 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
// Add to collision system
collisionSys.Add(playerCollider)
thatPlayerInNextFrame := nextRenderFramePlayers[i]
if currPlayerDownsync.InAir {
thatPlayerInNextFrame.VelX += GRAVITY_X
thatPlayerInNextFrame.VelY += GRAVITY_Y
if ATK_CHARACTER_STATE_ONWALL == currPlayerDownsync.CharacterState && !jumpedOrNotList[i] {
thatPlayerInNextFrame.VelX += GRAVITY_X
thatPlayerInNextFrame.VelY = chConfig.WallSlidingVelY
} else {
thatPlayerInNextFrame.VelX += GRAVITY_X
thatPlayerInNextFrame.VelY += GRAVITY_Y
}
}
}
// 3. Add bullet colliders into collision system
bulletColliders := make([]*resolv.Object, 0, len(currRenderFrame.MeleeBullets)) // Will all be removed at the end of this function due to the need for being rollback-compatible
for _, meleeBullet := range currRenderFrame.MeleeBullets {
if (meleeBullet.OriginatedRenderFrameId+meleeBullet.StartupFrames <= currRenderFrame.Id) && (meleeBullet.OriginatedRenderFrameId+meleeBullet.StartupFrames+meleeBullet.ActiveFrames > currRenderFrame.Id) {
offender := currRenderFrame.PlayersArr[meleeBullet.OffenderJoinIndex-1]
xfac := int32(1) // By now, straight Punch offset doesn't respect "y-axis"
if 0 > offender.DirX {
xfac = -xfac
// [WARNING] For rollback compatibility, static data of "BulletConfig" & "BattleAttr(static since instantiated)" can just be copies of the pointers in "RenderFrameBuffer", however, FireballBullets movement data as well as bullet animation data must be copies of instances for each RenderFrame!
bulletColliders := make([]*resolv.Object, 0, len(currRenderFrame.MeleeBullets)) // Will all be removed at the end of this function due to the need for being rollback-compatible
for _, prevMelee := range currRenderFrame.MeleeBullets {
meleeBullet := &MeleeBullet{
Bullet: prevMelee.Bullet,
BattleAttr: prevMelee.BattleAttr,
FramesInBlState: prevMelee.FramesInBlState + 1,
BlState: prevMelee.BlState,
}
if IsMeleeBulletAlive(meleeBullet, currRenderFrame) {
if IsMeleeBulletActive(meleeBullet, currRenderFrame) {
offender := currRenderFrame.PlayersArr[meleeBullet.BattleAttr.OffenderJoinIndex-1]
xfac := int32(1) // By now, straight Punch offset doesn't respect "y-axis"
if 0 > offender.DirX {
xfac = -xfac
}
bulletWx, bulletWy := VirtualGridToWorldPos(offender.VirtualGridX+xfac*meleeBullet.Bullet.HitboxOffsetX, offender.VirtualGridY)
hitboxSizeWx, hitboxSizeWy := VirtualGridToWorldPos(meleeBullet.Bullet.HitboxSizeX, meleeBullet.Bullet.HitboxSizeY)
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, hitboxSizeWx, hitboxSizeWy, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, collisionSpaceOffsetX, collisionSpaceOffsetY, meleeBullet, "MeleeBullet")
collisionSys.Add(newBulletCollider)
bulletColliders = append(bulletColliders, newBulletCollider)
meleeBullet.BlState = BULLET_ACTIVE
if meleeBullet.BlState != prevMelee.BlState {
meleeBullet.FramesInBlState = 0
}
}
bulletWx, bulletWy := VirtualGridToWorldPos(offender.VirtualGridX+xfac*meleeBullet.HitboxOffsetX, offender.VirtualGridY)
hitboxSizeWx, hitboxSizeWy := VirtualGridToWorldPos(meleeBullet.HitboxSizeX, meleeBullet.HitboxSizeY)
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, hitboxSizeWx, hitboxSizeWy, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, collisionSpaceOffsetX, collisionSpaceOffsetY, meleeBullet, "MeleeBullet")
collisionSys.Add(newBulletCollider)
bulletColliders = append(bulletColliders, newBulletCollider)
} else if meleeBullet.OriginatedRenderFrameId+meleeBullet.StartupFrames+meleeBullet.ActiveFrames > currRenderFrame.Id {
nextRenderFrameMeleeBullets = append(nextRenderFrameMeleeBullets, meleeBullet)
}
}
for _, fireballBullet := range currRenderFrame.FireballBullets {
if (fireballBullet.OriginatedRenderFrameId+fireballBullet.StartupFrames < currRenderFrame.Id) && (fireballBullet.OriginatedRenderFrameId+fireballBullet.StartupFrames+fireballBullet.ActiveFrames > currRenderFrame.Id) {
bulletWx, bulletWy := VirtualGridToWorldPos(fireballBullet.VirtualGridX, fireballBullet.VirtualGridY)
hitboxSizeWx, hitboxSizeWy := VirtualGridToWorldPos(fireballBullet.HitboxSizeX, fireballBullet.HitboxSizeY)
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, hitboxSizeWx, hitboxSizeWy, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, collisionSpaceOffsetX, collisionSpaceOffsetY, fireballBullet, "FireballBullet")
collisionSys.Add(newBulletCollider)
bulletColliders = append(bulletColliders, newBulletCollider)
} else if fireballBullet.OriginatedRenderFrameId+fireballBullet.StartupFrames+fireballBullet.ActiveFrames > currRenderFrame.Id {
for _, prevFireball := range currRenderFrame.FireballBullets {
fireballBullet := &FireballBullet{
VirtualGridX: prevFireball.VirtualGridX,
VirtualGridY: prevFireball.VirtualGridY,
DirX: prevFireball.DirX,
DirY: prevFireball.DirY,
VelX: prevFireball.VelX,
VelY: prevFireball.VelY,
Speed: prevFireball.Speed,
Bullet: prevFireball.Bullet,
BattleAttr: prevFireball.BattleAttr,
FramesInBlState: prevFireball.FramesInBlState + 1,
BlState: prevFireball.BlState,
}
if IsFireballBulletAlive(fireballBullet, currRenderFrame) {
if IsFireballBulletActive(fireballBullet, currRenderFrame) {
bulletWx, bulletWy := VirtualGridToWorldPos(fireballBullet.VirtualGridX, fireballBullet.VirtualGridY)
hitboxSizeWx, hitboxSizeWy := VirtualGridToWorldPos(fireballBullet.Bullet.HitboxSizeX, fireballBullet.Bullet.HitboxSizeY)
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, hitboxSizeWx, hitboxSizeWy, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, collisionSpaceOffsetX, collisionSpaceOffsetY, fireballBullet, "FireballBullet")
collisionSys.Add(newBulletCollider)
bulletColliders = append(bulletColliders, newBulletCollider)
fireballBullet.BlState = BULLET_ACTIVE
if fireballBullet.BlState != prevFireball.BlState {
fireballBullet.FramesInBlState = 0
}
fireballBullet.VirtualGridX, fireballBullet.VirtualGridY = fireballBullet.VirtualGridX+fireballBullet.VelX, fireballBullet.VirtualGridY+fireballBullet.VelY
//fmt.Printf("Pushing active fireball to next frame @currRenderFrame.Id=%d, bulletLocalId=%d, virtualGridX=%d, virtualGridY=%d, blState=%d\n", currRenderFrame.Id, fireballBullet.BattleAttr.BulletLocalId, fireballBullet.VirtualGridX, fireballBullet.VirtualGridY, fireballBullet.BlState)
} else {
//fmt.Printf("Pushing non-active fireball to next frame @currRenderFrame.Id=%d, bulletLocalId=%d, virtualGridX=%d, virtualGridY=%d, blState=%d\n", currRenderFrame.Id, fireballBullet.BattleAttr.BulletLocalId, fireballBullet.VirtualGridX, fireballBullet.VirtualGridY, fireballBullet.BlState)
}
nextRenderFrameFireballBullets = append(nextRenderFrameFireballBullets, fireballBullet)
}
}
@@ -634,8 +831,8 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
joinIndex := currPlayerDownsync.JoinIndex
playerCollider := playerColliders[i]
playerShape := playerCollider.Shape.(*resolv.ConvexPolygon)
hardPushbackNorms[joinIndex-1] = calcHardPushbacksNorms(joinIndex, playerCollider, playerShape, SNAP_INTO_PLATFORM_OVERLAP, &(effPushbacks[joinIndex-1]))
thatPlayerInNextFrame := nextRenderFramePlayers[i]
hardPushbackNorms[joinIndex-1] = calcHardPushbacksNorms(joinIndex, currPlayerDownsync, thatPlayerInNextFrame, playerCollider, playerShape, SNAP_INTO_PLATFORM_OVERLAP, &(effPushbacks[joinIndex-1]))
chConfig := chConfigsOrderedByJoinIndex[i]
landedOnGravityPushback := false
@@ -656,7 +853,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
continue
}
bShape := obj.Shape.(*resolv.ConvexPolygon)
overlapped, pushbackX, pushbackY, overlapResult := CalcPushbacks(0, 0, playerShape, bShape)
overlapped, pushbackX, pushbackY, overlapResult := calcPushbacks(0, 0, playerShape, bShape)
if !overlapped {
continue
}
@@ -684,24 +881,27 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
}
if landedOnGravityPushback {
thatPlayerInNextFrame.InAir = false
if currPlayerDownsync.InAir && 0 >= currPlayerDownsync.VelY {
// fallStopping
fallStopping := (currPlayerDownsync.InAir && 0 >= currPlayerDownsync.VelY)
if fallStopping {
thatPlayerInNextFrame.VelY = 0
thatPlayerInNextFrame.VelX = 0
if _, existent := nonAttackingSet[thatPlayerInNextFrame.CharacterState]; existent {
if ATK_CHARACTER_STATE_BLOWN_UP1 == thatPlayerInNextFrame.CharacterState {
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_LAY_DOWN1
thatPlayerInNextFrame.FramesToRecover = chConfig.LayDownFramesToRecover
} else {
if ATK_CHARACTER_STATE_BLOWN_UP1 == thatPlayerInNextFrame.CharacterState {
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_LAY_DOWN1
thatPlayerInNextFrame.FramesToRecover = chConfig.LayDownFramesToRecover
} else {
switch currPlayerDownsync.CharacterState {
case ATK_CHARACTER_STATE_BLOWN_UP1, ATK_CHARACTER_STATE_INAIR_IDLE1_NO_JUMP, ATK_CHARACTER_STATE_INAIR_IDLE1_BY_JUMP, ATK_CHARACTER_STATE_ONWALL:
// [WARNING] To prevent bouncing due to abrupt change of collider shape, it's important that we check "currPlayerDownsync" instead of "thatPlayerInNextFrame" here!
halfColliderWidthDiff, halfColliderHeightDiff := int32(0), currPlayerDownsync.ColliderRadius
_, halfColliderWorldHeightDiff := VirtualGridToWorldPos(halfColliderWidthDiff, halfColliderHeightDiff)
effPushbacks[joinIndex-1].Y -= halfColliderWorldHeightDiff // To prevent bouncing due to abrupt change of collider shape
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_IDLE1
effPushbacks[joinIndex-1].Y -= halfColliderWorldHeightDiff
}
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_IDLE1
thatPlayerInNextFrame.FramesToRecover = 0
}
} else {
// landedOnGravityPushback not fallStopping, could be in LayDown or GetUp
if _, existent := nonAttackingSet[thatPlayerInNextFrame.CharacterState]; existent {
// not fallStopping, could be in LayDown or GetUp
if ATK_CHARACTER_STATE_LAY_DOWN1 == thatPlayerInNextFrame.CharacterState {
if 0 == thatPlayerInNextFrame.FramesToRecover {
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_GET_UP1
@@ -716,30 +916,62 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
}
}
}
if chConfig.OnWallEnabled {
if thatPlayerInNextFrame.InAir {
// [WARNING] Sticking to wall MUST BE based on "InAir", otherwise we would get gravity reduction from ground up incorrectly!
if _, existent := noOpSet[currPlayerDownsync.CharacterState]; !existent {
// [WARNING] Sticking to wall could only be triggered by proactive player input
for _, hardPushbackNorm := range *hardPushbackNorms[joinIndex-1] {
normAlignmentWithHorizon1 := (hardPushbackNorm.X*float64(1.0) + hardPushbackNorm.Y*float64(0.0))
normAlignmentWithHorizon2 := (hardPushbackNorm.X*float64(-1.0) + hardPushbackNorm.Y*float64(0.0))
if VERTICAL_PLATFORM_THRESHOLD < normAlignmentWithHorizon1 {
thatPlayerInNextFrame.OnWall = true
thatPlayerInNextFrame.OnWallNormX, thatPlayerInNextFrame.OnWallNormY = int32(hardPushbackNorm.X), int32(hardPushbackNorm.Y)
break
}
if VERTICAL_PLATFORM_THRESHOLD < normAlignmentWithHorizon2 {
thatPlayerInNextFrame.OnWall = true
thatPlayerInNextFrame.OnWallNormX, thatPlayerInNextFrame.OnWallNormY = int32(hardPushbackNorm.X), int32(hardPushbackNorm.Y)
break
}
}
if !currPlayerDownsync.OnWall && thatPlayerInNextFrame.OnWall {
// To avoid mysterious climbing up the wall after sticking on it
thatPlayerInNextFrame.VelY = 0
}
}
}
if !thatPlayerInNextFrame.OnWall {
thatPlayerInNextFrame.OnWallNormX, thatPlayerInNextFrame.OnWallNormY = 0, 0
}
}
}
// 5. Check bullet-anything collisions
for _, bulletCollider := range bulletColliders {
collision := bulletCollider.Check(0, 0)
bulletCollider.Space.Remove(bulletCollider) // Make sure that the bulletCollider is always removed for each renderFrame
addToNextRenderFrame := true
exploded := false
if nil != collision {
switch v := bulletCollider.Data.(type) {
case *MeleeBullet:
bulletShape := bulletCollider.Shape.(*resolv.ConvexPolygon)
offender := currRenderFrame.PlayersArr[v.OffenderJoinIndex-1]
offender := currRenderFrame.PlayersArr[v.BattleAttr.OffenderJoinIndex-1]
for _, obj := range collision.Objects {
defenderShape := obj.Shape.(*resolv.ConvexPolygon)
switch t := obj.Data.(type) {
case *PlayerDownsync:
if v.OffenderJoinIndex == t.JoinIndex {
if v.BattleAttr.OffenderJoinIndex == t.JoinIndex {
continue
}
overlapped, _, _, _ := CalcPushbacks(0, 0, bulletShape, defenderShape)
overlapped, _, _, _ := calcPushbacks(0, 0, bulletShape, defenderShape)
if !overlapped {
continue
}
addToNextRenderFrame = false
exploded = true
if _, existent := invinsibleSet[t.CharacterState]; existent {
continue
}
@@ -750,38 +982,36 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
if 0 > offender.DirX {
xfac = -xfac
}
pushbackVelX, pushbackVelY := xfac*v.PushbackVelX, v.PushbackVelY
pushbackVelX, pushbackVelY := xfac*v.Bullet.PushbackVelX, v.Bullet.PushbackVelY
atkedPlayerInNextFrame := nextRenderFramePlayers[t.JoinIndex-1]
atkedPlayerInNextFrame.VelX = pushbackVelX
atkedPlayerInNextFrame.VelY = pushbackVelY
if v.BlowUp {
if v.Bullet.BlowUp {
atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_BLOWN_UP1
} else {
atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_ATKED1
}
oldFramesToRecover := nextRenderFramePlayers[t.JoinIndex-1].FramesToRecover
if v.HitStunFrames > oldFramesToRecover {
atkedPlayerInNextFrame.FramesToRecover = v.HitStunFrames
if v.Bullet.HitStunFrames > oldFramesToRecover {
atkedPlayerInNextFrame.FramesToRecover = v.Bullet.HitStunFrames
}
default:
addToNextRenderFrame = false
}
}
case *FireballBullet:
bulletShape := bulletCollider.Shape.(*resolv.ConvexPolygon)
offender := currRenderFrame.PlayersArr[v.OffenderJoinIndex-1]
offender := currRenderFrame.PlayersArr[v.BattleAttr.OffenderJoinIndex-1]
for _, obj := range collision.Objects {
defenderShape := obj.Shape.(*resolv.ConvexPolygon)
switch t := obj.Data.(type) {
case *PlayerDownsync:
if v.OffenderJoinIndex == t.JoinIndex {
if v.BattleAttr.OffenderJoinIndex == t.JoinIndex {
continue
}
overlapped, _, _, _ := CalcPushbacks(0, 0, bulletShape, defenderShape)
overlapped, _, _, _ := calcPushbacks(0, 0, bulletShape, defenderShape)
if !overlapped {
continue
}
addToNextRenderFrame = false
exploded = true
if _, existent := invinsibleSet[t.CharacterState]; existent {
continue
}
@@ -792,32 +1022,35 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
if 0 > offender.DirX {
xfac = -xfac
}
pushbackVelX, pushbackVelY := xfac*v.PushbackVelX, v.PushbackVelY
pushbackVelX, pushbackVelY := xfac*v.Bullet.PushbackVelX, v.Bullet.PushbackVelY
atkedPlayerInNextFrame := nextRenderFramePlayers[t.JoinIndex-1]
atkedPlayerInNextFrame.VelX = pushbackVelX
atkedPlayerInNextFrame.VelY = pushbackVelY
if v.BlowUp {
if v.Bullet.BlowUp {
atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_BLOWN_UP1
} else {
atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_ATKED1
}
oldFramesToRecover := nextRenderFramePlayers[t.JoinIndex-1].FramesToRecover
if v.HitStunFrames > oldFramesToRecover {
atkedPlayerInNextFrame.FramesToRecover = v.HitStunFrames
if v.Bullet.HitStunFrames > oldFramesToRecover {
atkedPlayerInNextFrame.FramesToRecover = v.Bullet.HitStunFrames
}
default:
addToNextRenderFrame = false
exploded = true
}
}
}
}
if addToNextRenderFrame {
if exploded {
switch v := bulletCollider.Data.(type) {
case *MeleeBullet:
nextRenderFrameMeleeBullets = append(nextRenderFrameMeleeBullets, v)
v.BlState = BULLET_EXPLODING
v.FramesInBlState = 0
//fmt.Printf("melee exploded @currRenderFrame.Id=%d, bulletLocalId=%d, blState=%d\n", currRenderFrame.Id, v.BattleAttr.BulletLocalId, v.BlState)
case *FireballBullet:
v.VirtualGridX, v.VirtualGridY = v.VirtualGridX+v.VelX, v.VirtualGridY+v.VelY
nextRenderFrameFireballBullets = append(nextRenderFrameFireballBullets, v)
v.BlState = BULLET_EXPLODING
v.FramesInBlState = 0
//fmt.Printf("fireball exploded @currRenderFrame.Id=%d, bulletLocalId=%d, virtualGridX=%d, virtualGridY=%d, blState=%d\n", currRenderFrame.Id, v.BattleAttr.BulletLocalId, v.VirtualGridX, v.VirtualGridY, v.BlState)
}
}
}
@@ -834,8 +1067,10 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
if thatPlayerInNextFrame.InAir {
oldNextCharacterState := thatPlayerInNextFrame.CharacterState
switch oldNextCharacterState {
case ATK_CHARACTER_STATE_IDLE1, ATK_CHARACTER_STATE_WALKING:
if jumpedOrNotList[i] || ATK_CHARACTER_STATE_INAIR_IDLE1_BY_JUMP == currPlayerDownsync.CharacterState {
case ATK_CHARACTER_STATE_IDLE1, ATK_CHARACTER_STATE_WALKING, ATK_CHARACTER_STATE_TURNAROUND:
if thatPlayerInNextFrame.OnWall {
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_ONWALL
} else if jumpedOrNotList[i] || ATK_CHARACTER_STATE_INAIR_IDLE1_BY_JUMP == currPlayerDownsync.CharacterState {
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_INAIR_IDLE1_BY_JUMP
} else {
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_INAIR_IDLE1_NO_JUMP
@@ -865,10 +1100,11 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
}
return &RoomDownsyncFrame{
Id: currRenderFrame.Id + 1,
PlayersArr: nextRenderFramePlayers,
MeleeBullets: nextRenderFrameMeleeBullets,
FireballBullets: nextRenderFrameFireballBullets,
Id: currRenderFrame.Id + 1,
PlayersArr: nextRenderFramePlayers,
BulletLocalIdCounter: bulletLocalId,
MeleeBullets: nextRenderFrameMeleeBullets,
FireballBullets: nextRenderFrameFireballBullets,
}
}
@@ -949,3 +1185,82 @@ func AlignPolygon2DToBoundingBox(input *Polygon2D) *Polygon2D {
return output
}
func NewMeleeBullet(bulletLocalId, originatedRenderFrameId, offenderJoinIndex, startupFrames, cancellableStFrame, cancellableEdFrame, activeFrames, hitStunFrames, blockStunFrames, pushbackVelX, pushbackVelY, damage, selfLockVelX, selfLockVelY, hitboxOffsetX, hitboxOffsetY, hitboxSizeX, hitboxSizeY int32, blowUp bool, teamId, blState, framesInBlState, explosionFrames, speciesId int32) *MeleeBullet {
return &MeleeBullet{
BlState: blState,
FramesInBlState: framesInBlState,
BattleAttr: &BulletBattleAttr{
BulletLocalId: bulletLocalId,
OriginatedRenderFrameId: originatedRenderFrameId,
OffenderJoinIndex: offenderJoinIndex,
TeamId: teamId,
},
Bullet: &BulletConfig{
StartupFrames: startupFrames,
CancellableStFrame: cancellableStFrame,
CancellableEdFrame: cancellableEdFrame,
ActiveFrames: activeFrames,
HitStunFrames: hitStunFrames,
BlockStunFrames: blockStunFrames,
PushbackVelX: pushbackVelX,
PushbackVelY: pushbackVelY,
Damage: damage,
SelfLockVelX: selfLockVelX,
SelfLockVelY: selfLockVelY,
HitboxOffsetX: hitboxOffsetX,
HitboxOffsetY: hitboxOffsetY,
HitboxSizeX: hitboxSizeX,
HitboxSizeY: hitboxSizeY,
BlowUp: blowUp,
ExplosionFrames: explosionFrames,
SpeciesId: speciesId,
},
}
}
func NewFireballBullet(bulletLocalId, originatedRenderFrameId, offenderJoinIndex, startupFrames, cancellableStFrame, cancellableEdFrame, activeFrames, hitStunFrames, blockStunFrames, pushbackVelX, pushbackVelY, damage, selfLockVelX, selfLockVelY, hitboxOffsetX, hitboxOffsetY, hitboxSizeX, hitboxSizeY int32, blowUp bool, teamId int32, virtualGridX, virtualGridY, dirX, dirY, velX, velY, speed, blState, framesInBlState, explosionFrames, speciesId int32) *FireballBullet {
return &FireballBullet{
VirtualGridX: virtualGridX,
VirtualGridY: virtualGridY,
DirX: dirX,
DirY: dirY,
VelX: velX,
VelY: velY,
Speed: speed,
BattleAttr: &BulletBattleAttr{
BulletLocalId: bulletLocalId,
OriginatedRenderFrameId: originatedRenderFrameId,
OffenderJoinIndex: offenderJoinIndex,
TeamId: teamId,
},
Bullet: &BulletConfig{
StartupFrames: startupFrames,
CancellableStFrame: cancellableStFrame,
CancellableEdFrame: cancellableEdFrame,
ActiveFrames: activeFrames,
HitStunFrames: hitStunFrames,
BlockStunFrames: blockStunFrames,
PushbackVelX: pushbackVelX,
PushbackVelY: pushbackVelY,
Damage: damage,
SelfLockVelX: selfLockVelX,
SelfLockVelY: selfLockVelY,
HitboxOffsetX: hitboxOffsetX,
HitboxOffsetY: hitboxOffsetY,
HitboxSizeX: hitboxSizeX,
HitboxSizeY: hitboxSizeY,
BlowUp: blowUp,
ExplosionFrames: explosionFrames,
SpeciesId: speciesId,
},
}
}

View File

@@ -15,8 +15,18 @@ type CharacterConfig struct {
GetUpInvinsibleFrames int32
GetUpFramesToRecover int32
Speed int32
JumpingInitVelY int32
Speed int32
JumpingInitVelY int32
JumpingFramesToRecover int32 // Not used yet
DashingEnabled bool
OnWallEnabled bool
WallJumpingFramesToRecover int32
WallJumpingInitVelX int32
WallJumpingInitVelY int32
WallSlidingVelY int32
InertiaFramesToRecover int32
SkillMapper SkillMapperType
}
@@ -35,8 +45,14 @@ var Characters = map[int]*CharacterConfig{
GetUpInvinsibleFrames: int32(10),
GetUpFramesToRecover: int32(27),
Speed: int32(float64(1.2) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingInitVelY: int32(float64(8) * WORLD_TO_VIRTUAL_GRID_RATIO),
Speed: int32(float64(2.1) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingInitVelY: int32(float64(8) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingFramesToRecover: int32(2),
InertiaFramesToRecover: int32(8),
DashingEnabled: false,
OnWallEnabled: false,
SkillMapper: func(patternId int, currPlayerDownsync *PlayerDownsync) int {
if 1 == patternId {
@@ -51,8 +67,8 @@ var Characters = map[int]*CharacterConfig{
if skillConfig, existent1 := skills[int(currPlayerDownsync.ActiveSkillId)]; existent1 {
switch v := skillConfig.Hits[currPlayerDownsync.ActiveSkillHit].(type) {
case *MeleeBullet:
if v.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.CancellableEdFrame {
if nextSkillId, existent2 := v.CancelTransit[patternId]; existent2 {
if v.Bullet.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.Bullet.CancellableEdFrame {
if nextSkillId, existent2 := v.Bullet.CancelTransit[patternId]; existent2 {
return nextSkillId
}
}
@@ -78,8 +94,18 @@ var Characters = map[int]*CharacterConfig{
GetUpInvinsibleFrames: int32(10),
GetUpFramesToRecover: int32(27),
Speed: int32(float64(1.4) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingInitVelY: int32(float64(7.5) * WORLD_TO_VIRTUAL_GRID_RATIO),
Speed: int32(float64(2.19) * WORLD_TO_VIRTUAL_GRID_RATIO), // I don't know why "2.2" is so special that it throws a compile error
JumpingInitVelY: int32(float64(7.5) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingFramesToRecover: int32(2),
InertiaFramesToRecover: int32(8),
DashingEnabled: true,
OnWallEnabled: true,
WallJumpingFramesToRecover: int32(8), // 8 would be the minimum for an avg human
WallJumpingInitVelX: int32(float64(2.8) * WORLD_TO_VIRTUAL_GRID_RATIO), // Default is "appeared facing right", but actually holding ctrl against left
WallJumpingInitVelY: int32(float64(7) * WORLD_TO_VIRTUAL_GRID_RATIO),
WallSlidingVelY: int32(float64(-1) * WORLD_TO_VIRTUAL_GRID_RATIO),
SkillMapper: func(patternId int, currPlayerDownsync *PlayerDownsync) int {
if 1 == patternId {
@@ -94,14 +120,17 @@ var Characters = map[int]*CharacterConfig{
if skillConfig, existent1 := skills[int(currPlayerDownsync.ActiveSkillId)]; existent1 {
switch v := skillConfig.Hits[currPlayerDownsync.ActiveSkillHit].(type) {
case *MeleeBullet:
if v.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.CancellableEdFrame {
if nextSkillId, existent2 := v.CancelTransit[patternId]; existent2 {
if v.Bullet.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.Bullet.CancellableEdFrame {
if nextSkillId, existent2 := v.Bullet.CancelTransit[patternId]; existent2 {
return nextSkillId
}
}
}
}
}
} else if 5 == patternId {
// Dashing is already constrained by "FramesToRecover & CapturedByInertia" in "deriveOpPattern"
return 12
}
// By default no skill can be fired
@@ -121,8 +150,14 @@ var Characters = map[int]*CharacterConfig{
GetUpInvinsibleFrames: int32(8),
GetUpFramesToRecover: int32(30),
Speed: int32(float64(1.0) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingInitVelY: int32(float64(9) * WORLD_TO_VIRTUAL_GRID_RATIO),
Speed: int32(float64(1.8) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingInitVelY: int32(float64(7.8) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingFramesToRecover: int32(2),
InertiaFramesToRecover: int32(8),
DashingEnabled: false,
OnWallEnabled: false,
SkillMapper: func(patternId int, currPlayerDownsync *PlayerDownsync) int {
if 1 == patternId {
@@ -130,21 +165,29 @@ var Characters = map[int]*CharacterConfig{
if currPlayerDownsync.InAir {
return 257
} else {
return 10
return 7
}
} else {
// Now that "0 < FramesToRecover", we're only able to fire any skill if it's a cancellation
if skillConfig, existent1 := skills[int(currPlayerDownsync.ActiveSkillId)]; existent1 {
switch v := skillConfig.Hits[currPlayerDownsync.ActiveSkillHit].(type) {
case *MeleeBullet:
if v.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.CancellableEdFrame {
if nextSkillId, existent2 := v.CancelTransit[patternId]; existent2 {
if v.Bullet.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.Bullet.CancellableEdFrame {
if nextSkillId, existent2 := v.Bullet.CancelTransit[patternId]; existent2 {
return nextSkillId
}
}
}
}
}
} else if 2 == patternId {
if 0 == currPlayerDownsync.FramesToRecover && !currPlayerDownsync.InAir {
return 11
}
} else if 3 == patternId {
if 0 == currPlayerDownsync.FramesToRecover && !currPlayerDownsync.InAir {
return 10
}
}
// By default no skill can be fired
@@ -162,7 +205,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK1,
Hits: []interface{}{
&MeleeBullet{
Bullet: Bullet{
Bullet: &BulletConfig{
StartupFrames: int32(7),
ActiveFrames: int32(22),
HitStunFrames: int32(13),
@@ -182,7 +225,9 @@ var skills = map[int]*Skill{
CancelTransit: map[int]int{
1: 2,
},
// TODO: Use non-zero "selfLockVel"
BlowUp: false,
ExplosionFrames: 9,
SpeciesId: int32(1),
},
},
},
@@ -195,7 +240,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK2,
Hits: []interface{}{
&MeleeBullet{
Bullet: Bullet{
Bullet: &BulletConfig{
StartupFrames: int32(18),
ActiveFrames: int32(18),
HitStunFrames: int32(18),
@@ -214,6 +259,9 @@ var skills = map[int]*Skill{
CancelTransit: map[int]int{
1: 3,
},
BlowUp: false,
ExplosionFrames: 9,
SpeciesId: int32(1),
},
},
},
@@ -226,8 +274,8 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK3,
Hits: []interface{}{
&MeleeBullet{
Bullet: Bullet{
StartupFrames: int32(15),
Bullet: &BulletConfig{
StartupFrames: int32(8),
ActiveFrames: int32(30),
HitStunFrames: MAX_INT32,
BlockStunFrames: int32(9),
@@ -236,11 +284,13 @@ var skills = map[int]*Skill{
SelfLockVelY: int32(float64(5) * WORLD_TO_VIRTUAL_GRID_RATIO),
PushbackVelX: int32(float64(2) * WORLD_TO_VIRTUAL_GRID_RATIO),
PushbackVelY: int32(float64(7) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetY: int32(0),
HitboxSizeX: int32(float64(48) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetX: int32(float64(16) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetY: int32(float64(8) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeY: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
BlowUp: true,
ExplosionFrames: 9,
SpeciesId: int32(1),
},
},
},
@@ -253,7 +303,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK1,
Hits: []interface{}{
&MeleeBullet{
Bullet: Bullet{
Bullet: &BulletConfig{
StartupFrames: int32(7),
ActiveFrames: int32(22),
HitStunFrames: int32(13),
@@ -273,7 +323,9 @@ var skills = map[int]*Skill{
CancelTransit: map[int]int{
1: 5,
},
// TODO: Use non-zero "selfLockVel"
BlowUp: false,
ExplosionFrames: 15,
SpeciesId: int32(2),
},
},
},
@@ -286,7 +338,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK2,
Hits: []interface{}{
&MeleeBullet{
Bullet: Bullet{
Bullet: &BulletConfig{
StartupFrames: int32(18),
ActiveFrames: int32(18),
HitStunFrames: int32(18),
@@ -300,11 +352,14 @@ var skills = map[int]*Skill{
HitboxOffsetY: int32(0),
HitboxSizeX: int32(float64(24) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeY: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
CancellableStFrame: int32(22),
CancellableStFrame: int32(23),
CancellableEdFrame: int32(36),
CancelTransit: map[int]int{
1: 6,
},
BlowUp: false,
ExplosionFrames: 15,
SpeciesId: int32(2),
},
},
},
@@ -317,21 +372,23 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK3,
Hits: []interface{}{
&MeleeBullet{
Bullet: Bullet{
StartupFrames: int32(15),
Bullet: &BulletConfig{
StartupFrames: int32(8),
ActiveFrames: int32(28),
HitStunFrames: MAX_INT32,
BlockStunFrames: int32(9),
Damage: int32(10),
SelfLockVelX: int32(float64(-0.1) * WORLD_TO_VIRTUAL_GRID_RATIO),
SelfLockVelX: NO_LOCK_VEL,
SelfLockVelY: NO_LOCK_VEL,
PushbackVelX: int32(float64(2) * WORLD_TO_VIRTUAL_GRID_RATIO),
PushbackVelY: int32(float64(7) * WORLD_TO_VIRTUAL_GRID_RATIO),
PushbackVelY: int32(float64(3) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetX: int32(float64(24) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetY: int32(0),
HitboxSizeX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeY: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
BlowUp: true,
ExplosionFrames: 15,
SpeciesId: int32(2),
},
},
},
@@ -344,13 +401,13 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK1,
Hits: []interface{}{
&MeleeBullet{
Bullet: Bullet{
Bullet: &BulletConfig{
StartupFrames: int32(7),
ActiveFrames: int32(22),
HitStunFrames: int32(13),
BlockStunFrames: int32(9),
Damage: int32(5),
SelfLockVelX: int32(float64(0.05) * WORLD_TO_VIRTUAL_GRID_RATIO),
SelfLockVelX: NO_LOCK_VEL,
SelfLockVelY: NO_LOCK_VEL,
PushbackVelX: int32(float64(0.5) * WORLD_TO_VIRTUAL_GRID_RATIO),
PushbackVelY: int32(0),
@@ -362,9 +419,11 @@ var skills = map[int]*Skill{
CancellableEdFrame: int32(30),
CancelTransit: map[int]int{
1: 2,
1: 8,
},
// TODO: Use non-zero "selfLockVel"
BlowUp: false,
ExplosionFrames: 9,
SpeciesId: int32(1),
},
},
},
@@ -377,7 +436,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK2,
Hits: []interface{}{
&MeleeBullet{
Bullet: Bullet{
Bullet: &BulletConfig{
StartupFrames: int32(18),
ActiveFrames: int32(18),
HitStunFrames: int32(18),
@@ -394,34 +453,40 @@ var skills = map[int]*Skill{
CancellableStFrame: int32(22),
CancellableEdFrame: int32(36),
CancelTransit: map[int]int{
1: 3,
1: 9,
},
BlowUp: false,
ExplosionFrames: 9,
SpeciesId: int32(1),
},
},
},
},
9: &Skill{
RecoveryFrames: int32(50),
RecoveryFramesOnBlock: int32(50),
RecoveryFramesOnHit: int32(50),
RecoveryFrames: int32(40),
RecoveryFramesOnBlock: int32(40),
RecoveryFramesOnHit: int32(40),
ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_ATK3,
Hits: []interface{}{
&MeleeBullet{
Bullet: Bullet{
StartupFrames: int32(15),
Bullet: &BulletConfig{
StartupFrames: int32(7),
ActiveFrames: int32(30),
HitStunFrames: MAX_INT32,
BlockStunFrames: int32(9),
Damage: int32(10),
SelfLockVelX: int32(float64(0.5) * WORLD_TO_VIRTUAL_GRID_RATIO),
SelfLockVelY: int32(float64(5) * WORLD_TO_VIRTUAL_GRID_RATIO),
SelfLockVelX: int32(float64(1) * WORLD_TO_VIRTUAL_GRID_RATIO),
SelfLockVelY: NO_LOCK_VEL,
PushbackVelX: int32(float64(2) * WORLD_TO_VIRTUAL_GRID_RATIO),
PushbackVelY: int32(float64(7) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
PushbackVelY: int32(float64(4) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetX: int32(float64(10) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetY: int32(0),
HitboxSizeX: int32(float64(48) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeY: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
BlowUp: true,
ExplosionFrames: 9,
SpeciesId: int32(1),
},
},
},
@@ -434,9 +499,9 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK4,
Hits: []interface{}{
&FireballBullet{
Speed: int32(float64(8) * WORLD_TO_VIRTUAL_GRID_RATIO),
Bullet: Bullet{
StartupFrames: int32(15),
Speed: int32(float64(5) * WORLD_TO_VIRTUAL_GRID_RATIO),
Bullet: &BulletConfig{
StartupFrames: int32(12),
ActiveFrames: MAX_INT32,
HitStunFrames: int32(15),
BlockStunFrames: int32(9),
@@ -445,10 +510,69 @@ var skills = map[int]*Skill{
SelfLockVelY: NO_LOCK_VEL,
PushbackVelX: int32(float64(2) * WORLD_TO_VIRTUAL_GRID_RATIO),
PushbackVelY: int32(0),
HitboxOffsetX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetY: int32(0),
HitboxOffsetX: int32(float64(24) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetY: int32(float64(8) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeX: int32(float64(48) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeY: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
BlowUp: false,
ExplosionFrames: 15,
SpeciesId: int32(1),
},
},
},
},
11: &Skill{
RecoveryFrames: int32(60),
RecoveryFramesOnBlock: int32(60),
RecoveryFramesOnHit: int32(60),
ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_ATK5,
Hits: []interface{}{
&MeleeBullet{
Bullet: &BulletConfig{
StartupFrames: int32(3),
ActiveFrames: int32(25),
HitStunFrames: MAX_INT32,
BlockStunFrames: int32(9),
Damage: int32(30),
SelfLockVelX: int32(float64(1) * WORLD_TO_VIRTUAL_GRID_RATIO),
SelfLockVelY: int32(float64(8) * WORLD_TO_VIRTUAL_GRID_RATIO),
PushbackVelX: int32(float64(2) * WORLD_TO_VIRTUAL_GRID_RATIO),
PushbackVelY: int32(float64(7) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetX: int32(float64(8) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetY: int32(0),
HitboxSizeX: int32(float64(40) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeY: int32(float64(64) * WORLD_TO_VIRTUAL_GRID_RATIO),
BlowUp: true,
ExplosionFrames: 15,
SpeciesId: int32(3),
},
},
},
},
12: &Skill{
RecoveryFrames: int32(15),
RecoveryFramesOnBlock: int32(15),
RecoveryFramesOnHit: int32(15),
ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_DASHING,
Hits: []interface{}{
&MeleeBullet{
Bullet: &BulletConfig{
StartupFrames: int32(0),
ActiveFrames: int32(0),
HitStunFrames: MAX_INT32,
BlockStunFrames: int32(0),
Damage: int32(0),
SelfLockVelX: int32(float64(9) * WORLD_TO_VIRTUAL_GRID_RATIO),
SelfLockVelY: int32(0),
PushbackVelX: NO_LOCK_VEL,
PushbackVelY: NO_LOCK_VEL,
HitboxOffsetX: int32(0),
HitboxOffsetY: int32(0),
HitboxSizeX: int32(0),
HitboxSizeY: int32(0),
BlowUp: false,
},
},
},
@@ -461,7 +585,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1,
Hits: []interface{}{
&MeleeBullet{
Bullet: Bullet{
Bullet: &BulletConfig{
StartupFrames: int32(3),
ActiveFrames: int32(20),
HitStunFrames: int32(18),
@@ -475,6 +599,9 @@ var skills = map[int]*Skill{
HitboxOffsetY: int32(0),
HitboxSizeX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeY: int32(float64(24) * WORLD_TO_VIRTUAL_GRID_RATIO),
BlowUp: false,
ExplosionFrames: 9,
SpeciesId: int32(1),
},
},
},
@@ -487,7 +614,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1,
Hits: []interface{}{
&MeleeBullet{
Bullet: Bullet{
Bullet: &BulletConfig{
StartupFrames: int32(3),
ActiveFrames: int32(10),
HitStunFrames: int32(15),
@@ -501,6 +628,9 @@ var skills = map[int]*Skill{
HitboxOffsetY: int32(0),
HitboxSizeX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeY: int32(float64(24) * WORLD_TO_VIRTUAL_GRID_RATIO),
BlowUp: false,
ExplosionFrames: 15,
SpeciesId: int32(2),
},
},
},
@@ -513,7 +643,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1,
Hits: []interface{}{
&MeleeBullet{
Bullet: Bullet{
Bullet: &BulletConfig{
StartupFrames: int32(3),
ActiveFrames: int32(20),
HitStunFrames: int32(18),
@@ -527,6 +657,9 @@ var skills = map[int]*Skill{
HitboxOffsetY: int32(0),
HitboxSizeX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeY: int32(float64(24) * WORLD_TO_VIRTUAL_GRID_RATIO),
BlowUp: false,
ExplosionFrames: 9,
SpeciesId: int32(1),
},
},
},

View File

@@ -33,6 +33,11 @@ type PlayerDownsync struct {
MaxHp int32
CharacterState int32
InAir bool
OnWall bool
OnWallNormX int32
OnWallNormY int32
CapturedByInertia bool
ActiveSkillId int32
ActiveSkillHit int32
@@ -59,16 +64,11 @@ type Barrier struct {
Boundary *Polygon2D
}
type Bullet struct {
BulletLocalId int32 // for referencing cached nodes in frontend rendering
// for offender
OriginatedRenderFrameId int32 // Copied from the first bullet for all subsequent bullets
OffenderJoinIndex int32 // Copied to favor collision handling of the dispatched bullet
StartupFrames int32 // from "OriginatedRenderFrameId"
CancellableStFrame int32 // from "OriginatedRenderFrameId"
CancellableEdFrame int32 // from "OriginatedRenderFrameId"
ActiveFrames int32
type BulletConfig struct {
StartupFrames int32 // from "OriginatedRenderFrameId"
CancellableStFrame int32 // from "OriginatedRenderFrameId"
CancellableEdFrame int32 // from "OriginatedRenderFrameId"
ActiveFrames int32
// for defender
HitStunFrames int32
@@ -85,26 +85,41 @@ type Bullet struct {
HitboxSizeX int32
HitboxSizeY int32
BlowUp bool
BlowUp bool
ExplosionFrames int32
SpeciesId int32 // For fireball, this SpeciesId specifies both the active animation and the explosion animation, for melee it specifies the explosion animation
CancelTransit map[int]int
}
TeamId int32
type BulletBattleAttr struct {
BulletLocalId int32 // for referencing cached nodes in frontend rendering
// for offender
OriginatedRenderFrameId int32 // Copied from the first bullet for all subsequent bullets
OffenderJoinIndex int32 // Copied to favor collision handling of the dispatched bullet
TeamId int32
}
type MeleeBullet struct {
Bullet
BlState int32 // bullet state, e.g. STARTUP, ACTIVE, EXPLODING
FramesInBlState int32
BattleAttr *BulletBattleAttr
Bullet *BulletConfig
}
type FireballBullet struct {
VirtualGridX int32
VirtualGridY int32
DirX int32
DirY int32
VelX int32
VelY int32
Speed int32
Bullet
VirtualGridX int32
VirtualGridY int32
DirX int32
DirY int32
VelX int32
VelY int32
Speed int32
BlState int32 // bullet state, e.g. STARTUP, ACTIVE, EXPLODING
FramesInBlState int32
BattleAttr *BulletBattleAttr
Bullet *BulletConfig
}
type Skill struct {
@@ -115,6 +130,7 @@ type Skill struct {
ReleaseTriggerType int32 // 1: rising-edge, 2: falling-edge
BoundChState int32
Hits []interface{} // Hits within a "Skill" are automatically triggered
// [WARN] Multihit of a fireball is more difficult to handle than that of melee, because we have to count from the fireball's first hit; the situation becomes even more complicated when a multihit fireball is in a crowd -- remains to be designed
}
type RoomDownsyncFrame struct {

View File

@@ -42,7 +42,7 @@ func NewBarrierJs(boundary *Polygon2D) *js.Object {
})
}
func NewPlayerDownsyncJs(id, virtualGridX, virtualGridY, dirX, dirY, velX, velY, framesToRecover, framesInChState, activeSkillId, activeSkillHit, framesInvinsible, speed, battleState, characterState, joinIndex, hp, maxHp, colliderRadius int32, inAir bool, bulletTeamId, chCollisionTeamId int32) *js.Object {
func NewPlayerDownsyncJs(id, virtualGridX, virtualGridY, dirX, dirY, velX, velY, framesToRecover, framesInChState, activeSkillId, activeSkillHit, framesInvinsible, speed, battleState, characterState, joinIndex, hp, maxHp, colliderRadius int32, inAir, onWall bool, onWallNormX, onWallNormY int32, capturedByInertia bool, bulletTeamId, chCollisionTeamId int32) *js.Object {
return js.MakeWrapper(&PlayerDownsync{
Id: id,
VirtualGridX: virtualGridX,
@@ -64,82 +64,21 @@ func NewPlayerDownsyncJs(id, virtualGridX, virtualGridY, dirX, dirY, velX, velY,
MaxHp: maxHp,
ColliderRadius: colliderRadius,
InAir: inAir,
OnWall: onWall,
OnWallNormX: onWallNormX,
OnWallNormY: onWallNormY,
CapturedByInertia: capturedByInertia,
BulletTeamId: bulletTeamId,
ChCollisionTeamId: chCollisionTeamId,
})
}
func NewMeleeBulletJs(bulletLocalId, originatedRenderFrameId, offenderJoinIndex, startupFrames, cancellableStFrame, cancellableEdFrame, activeFrames, hitStunFrames, blockStunFrames, pushbackVelX, pushbackVelY, damage, selfLockVelX, selfLockVelY, hitboxOffsetX, hitboxOffsetY, hitboxSizeX, hitboxSizeY int32, blowUp bool, teamId int32) *js.Object {
return js.MakeWrapper(&MeleeBullet{
Bullet: Bullet{
BulletLocalId: bulletLocalId,
OriginatedRenderFrameId: originatedRenderFrameId,
OffenderJoinIndex: offenderJoinIndex,
StartupFrames: startupFrames,
CancellableStFrame: cancellableStFrame,
CancellableEdFrame: cancellableEdFrame,
ActiveFrames: activeFrames,
HitStunFrames: hitStunFrames,
BlockStunFrames: blockStunFrames,
PushbackVelX: pushbackVelX,
PushbackVelY: pushbackVelY,
Damage: damage,
SelfLockVelX: selfLockVelX,
SelfLockVelY: selfLockVelY,
HitboxOffsetX: hitboxOffsetX,
HitboxOffsetY: hitboxOffsetY,
HitboxSizeX: hitboxSizeX,
HitboxSizeY: hitboxSizeY,
BlowUp: blowUp,
TeamId: teamId,
},
})
func NewMeleeBulletJs(bulletLocalId, originatedRenderFrameId, offenderJoinIndex, startupFrames, cancellableStFrame, cancellableEdFrame, activeFrames, hitStunFrames, blockStunFrames, pushbackVelX, pushbackVelY, damage, selfLockVelX, selfLockVelY, hitboxOffsetX, hitboxOffsetY, hitboxSizeX, hitboxSizeY int32, blowUp bool, teamId, blState, framesInBlState, explosionFrames, speciesId int32) *js.Object {
return js.MakeWrapper(NewMeleeBullet(bulletLocalId, originatedRenderFrameId, offenderJoinIndex, startupFrames, cancellableStFrame, cancellableEdFrame, activeFrames, hitStunFrames, blockStunFrames, pushbackVelX, pushbackVelY, damage, selfLockVelX, selfLockVelY, hitboxOffsetX, hitboxOffsetY, hitboxSizeX, hitboxSizeY, blowUp, teamId, blState, framesInBlState, explosionFrames, speciesId))
}
func NewFireballBulletJs(bulletLocalId, originatedRenderFrameId, offenderJoinIndex, startupFrames, cancellableStFrame, cancellableEdFrame, activeFrames, hitStunFrames, blockStunFrames, pushbackVelX, pushbackVelY, damage, selfLockVelX, selfLockVelY, hitboxOffsetX, hitboxOffsetY, hitboxSizeX, hitboxSizeY int32, blowUp bool, teamId int32, virtualGridX, virtualGridY, dirX, dirY, velX, velY, speed int32) *js.Object {
return js.MakeWrapper(&FireballBullet{
VirtualGridX: virtualGridX,
VirtualGridY: virtualGridY,
DirX: dirX,
DirY: dirY,
VelX: velX,
VelY: velY,
Speed: speed,
Bullet: Bullet{
BulletLocalId: bulletLocalId,
OriginatedRenderFrameId: originatedRenderFrameId,
OffenderJoinIndex: offenderJoinIndex,
StartupFrames: startupFrames,
CancellableStFrame: cancellableStFrame,
CancellableEdFrame: cancellableEdFrame,
ActiveFrames: activeFrames,
HitStunFrames: hitStunFrames,
BlockStunFrames: blockStunFrames,
PushbackVelX: pushbackVelX,
PushbackVelY: pushbackVelY,
Damage: damage,
SelfLockVelX: selfLockVelX,
SelfLockVelY: selfLockVelY,
HitboxOffsetX: hitboxOffsetX,
HitboxOffsetY: hitboxOffsetY,
HitboxSizeX: hitboxSizeX,
HitboxSizeY: hitboxSizeY,
BlowUp: blowUp,
TeamId: teamId,
},
})
func NewFireballBulletJs(bulletLocalId, originatedRenderFrameId, offenderJoinIndex, startupFrames, cancellableStFrame, cancellableEdFrame, activeFrames, hitStunFrames, blockStunFrames, pushbackVelX, pushbackVelY, damage, selfLockVelX, selfLockVelY, hitboxOffsetX, hitboxOffsetY, hitboxSizeX, hitboxSizeY int32, blowUp bool, teamId int32, virtualGridX, virtualGridY, dirX, dirY, velX, velY, speed, blState, framesInBlState, explosionFrames, speciesId int32) *js.Object {
return js.MakeWrapper(NewFireballBullet(bulletLocalId, originatedRenderFrameId, offenderJoinIndex, startupFrames, cancellableStFrame, cancellableEdFrame, activeFrames, hitStunFrames, blockStunFrames, pushbackVelX, pushbackVelY, damage, selfLockVelX, selfLockVelY, hitboxOffsetX, hitboxOffsetY, hitboxSizeX, hitboxSizeY, blowUp, teamId, virtualGridX, virtualGridY, dirX, dirY, velX, velY, speed, blState, framesInBlState, explosionFrames, speciesId))
}
func NewNpcPatrolCue(flAct, frAct uint64, x, y float64) *js.Object {
@@ -233,5 +172,9 @@ func main() {
"ConvertToFirstUsedRenderFrameId": ConvertToFirstUsedRenderFrameId,
"ConvertToLastUsedRenderFrameId": ConvertToLastUsedRenderFrameId,
"ShouldGenerateInputFrameUpsync": ShouldGenerateInputFrameUpsync,
"IsMeleeBulletActive": IsMeleeBulletActive,
"IsMeleeBulletAlive": IsMeleeBulletAlive,
"IsFireballBulletActive": IsFireballBulletActive,
"IsFireballBulletAlive": IsFireballBulletAlive,
})
}

View File

@@ -66,4 +66,21 @@ hp application/json application/javascript;
proxy_pass http://tsrht_cluster/tsrht$is_args$args;
}
location ~^/tsrhtSecondary$ {
# Reference http://www.tornadoweb.org/en/stable/guide/running.html
proxy_pass_header Server;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme;
# Reverse-proxy for ws connection.
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://tsrht_cluster/tsrhtSecondary$is_args$args;
}
}