Fixed fireball rollback mechanism.

This commit is contained in:
genxium 2023-01-13 11:25:20 +08:00
parent 29e402ea71
commit dd9c03404e
16 changed files with 7116 additions and 341 deletions

View File

@ -55,62 +55,62 @@ func toPbRoomDownsyncFrame(rdf *battle.RoomDownsyncFrame) *pb.RoomDownsyncFrame
for i, last := range rdf.MeleeBullets { for i, last := range rdf.MeleeBullets {
pbBullet := &pb.MeleeBullet{ pbBullet := &pb.MeleeBullet{
BulletLocalId: last.BulletLocalId, BulletLocalId: last.Bullet.BulletLocalId,
OriginatedRenderFrameId: last.OriginatedRenderFrameId, OriginatedRenderFrameId: last.Bullet.OriginatedRenderFrameId,
OffenderJoinIndex: last.OffenderJoinIndex, OffenderJoinIndex: last.Bullet.OffenderJoinIndex,
StartupFrames: last.StartupFrames, StartupFrames: last.Bullet.StartupFrames,
CancellableStFrame: last.CancellableStFrame, CancellableStFrame: last.Bullet.CancellableStFrame,
CancellableEdFrame: last.CancellableEdFrame, CancellableEdFrame: last.Bullet.CancellableEdFrame,
ActiveFrames: last.ActiveFrames, ActiveFrames: last.Bullet.ActiveFrames,
HitStunFrames: last.HitStunFrames, HitStunFrames: last.Bullet.HitStunFrames,
BlockStunFrames: last.BlockStunFrames, BlockStunFrames: last.Bullet.BlockStunFrames,
PushbackVelX: last.PushbackVelX, PushbackVelX: last.Bullet.PushbackVelX,
PushbackVelY: last.PushbackVelY, PushbackVelY: last.Bullet.PushbackVelY,
Damage: last.Damage, Damage: last.Bullet.Damage,
SelfLockVelX: last.SelfLockVelX, SelfLockVelX: last.Bullet.SelfLockVelX,
SelfLockVelY: last.SelfLockVelY, SelfLockVelY: last.Bullet.SelfLockVelY,
HitboxOffsetX: last.HitboxOffsetX, HitboxOffsetX: last.Bullet.HitboxOffsetX,
HitboxOffsetY: last.HitboxOffsetY, HitboxOffsetY: last.Bullet.HitboxOffsetY,
HitboxSizeX: last.HitboxSizeX, HitboxSizeX: last.Bullet.HitboxSizeX,
HitboxSizeY: last.HitboxSizeY, HitboxSizeY: last.Bullet.HitboxSizeY,
BlowUp: last.BlowUp, BlowUp: last.Bullet.BlowUp,
TeamId: last.TeamId, TeamId: last.Bullet.TeamId,
} }
ret.MeleeBullets[i] = pbBullet ret.MeleeBullets[i] = pbBullet
} }
for i, last := range rdf.FireballBullets { for i, last := range rdf.FireballBullets {
pbBullet := &pb.FireballBullet{ pbBullet := &pb.FireballBullet{
BulletLocalId: last.BulletLocalId, BulletLocalId: last.Bullet.BulletLocalId,
OriginatedRenderFrameId: last.OriginatedRenderFrameId, OriginatedRenderFrameId: last.Bullet.OriginatedRenderFrameId,
OffenderJoinIndex: last.OffenderJoinIndex, OffenderJoinIndex: last.Bullet.OffenderJoinIndex,
StartupFrames: last.StartupFrames, StartupFrames: last.Bullet.StartupFrames,
CancellableStFrame: last.CancellableStFrame, CancellableStFrame: last.Bullet.CancellableStFrame,
CancellableEdFrame: last.CancellableEdFrame, CancellableEdFrame: last.Bullet.CancellableEdFrame,
ActiveFrames: last.ActiveFrames, ActiveFrames: last.Bullet.ActiveFrames,
HitStunFrames: last.HitStunFrames, HitStunFrames: last.Bullet.HitStunFrames,
BlockStunFrames: last.BlockStunFrames, BlockStunFrames: last.Bullet.BlockStunFrames,
PushbackVelX: last.PushbackVelX, PushbackVelX: last.Bullet.PushbackVelX,
PushbackVelY: last.PushbackVelY, PushbackVelY: last.Bullet.PushbackVelY,
Damage: last.Damage, Damage: last.Bullet.Damage,
SelfLockVelX: last.SelfLockVelX, SelfLockVelX: last.Bullet.SelfLockVelX,
SelfLockVelY: last.SelfLockVelY, SelfLockVelY: last.Bullet.SelfLockVelY,
HitboxOffsetX: last.HitboxOffsetX, HitboxOffsetX: last.Bullet.HitboxOffsetX,
HitboxOffsetY: last.HitboxOffsetY, HitboxOffsetY: last.Bullet.HitboxOffsetY,
HitboxSizeX: last.HitboxSizeX, HitboxSizeX: last.Bullet.HitboxSizeX,
HitboxSizeY: last.HitboxSizeY, HitboxSizeY: last.Bullet.HitboxSizeY,
BlowUp: last.BlowUp, BlowUp: last.Bullet.BlowUp,
TeamId: last.TeamId, TeamId: last.Bullet.TeamId,
VirtualGridX: last.VirtualGridX, VirtualGridX: last.VirtualGridX,
VirtualGridY: last.VirtualGridY, VirtualGridY: last.VirtualGridY,

View File

@ -335,7 +335,20 @@ func (pR *Room) playerDownsyncStr(player *battle.PlayerDownsync) string {
if player.InAir { if player.InAir {
inAirInt = 1 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.Bullet.BulletLocalId, fireball.Bullet.OriginatedRenderFrameId, fireball.Bullet.OffenderJoinIndex, fireball.VirtualGridX, fireball.VirtualGridY, fireball.VelX, fireball.VelY, fireball.DirX, fireball.DirY, fireball.Bullet.HitboxSizeX, fireball.Bullet.HitboxSizeY)
return s return s
} }
@ -365,7 +378,11 @@ func (pR *Room) rdfIdToActuallyUsedInputString() string {
for _, player := range rdf.PlayersArr { for _, player := range rdf.PlayersArr {
playersStrBldr = append(playersStrBldr, pR.playerDownsyncStr(player)) 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") return strings.Join(s, "\n")

File diff suppressed because one or more lines are too long

View File

@ -62,7 +62,7 @@
{ {
"frame": 0.13333333333333333, "frame": 0.13333333333333333,
"value": { "value": {
"__uuid__": "2ad9becb-20e0-4bbb-b83b-de21e085e706" "__uuid__": "dbe67025-9878-4e13-8f3d-81e04734810a"
} }
}, },
{ {

View File

@ -5,14 +5,14 @@
<tileset firstgid="129" source="tiles2.tsx"/> <tileset firstgid="129" source="tiles2.tsx"/>
<layer id="6" name="Ground" width="128" height="64"> <layer id="6" name="Ground" width="128" height="64">
<data encoding="base64" compression="zlib"> <data encoding="base64" compression="zlib">
eJzt2z1uAjEURWELlIYuiKRHyk4iGjo2wP6XkRDGUmThnxne+FncU3wNEDJ+x3aqbEMIWwAAAAAAAAAAAADo4IQ/3h08+3s/gzflGSivnRlor50ZaK+dGdTX/mb0e6y+h/7+/Q+NHn1P6z7YG32G/svWXur1TP/SvqL/OP1LnSz6t7Qt9a29T//x+7fcASW9ZvDKWvpbmbPHRprBKxt97e8ZSjPo3f/L4TnSOyDXfY19QP+xtLa32gcjzsCjf+u5Pxp9ZhT0v9tN6K/jtvbvRLwH0tejY6Pcz48mzsC7hVf/zSSe/+uvc8bGQO5veO39pWrPo37+0/438Q74/5pV/9HQ/+6c9H7EevafK5h799A/b5eZmdX9W+u1ZD/NaU//ED4mpZk9c/5Le6DX+S/tT/rn+1so3QM9+tfuJ/X+8O/g2f8ijv7a6K+N/tror43+2uivjf7a6K+N/tror43+2uivjf7a6K+N/tror43+2uivjf7a6K+N/trory3+D5R3C/rTn/70790f6/X/AbS6syo= eJzt2ztuAjEURmELlIYuiKRHyk4iGjo2wP6XkRDGUmThxwx3fC3+U3wNw8v3eEyabEMIWwAAAAAAAAAAAADo4IQ/3h08+3t/B2/KM1BeOzPQXjsz0F47M6iv/c3oc6zeh/7+/Q+NHr1P6z7YGz2H/svWXur1TP/SvqL/OP1LnSz6t7Qt9a1dp//4/VvOgJJeM3hlLf2tzNljI83glY2+9vcMpRko9E/PgFz3NfbBKDNQ7r+kvdU+GHEGHv2/Gl9zNHrOKOh/t5vQX8dt7d+JeC19PDo2yr1+NHEG3i28+m8m8f6//jpnbAzkfsNr15eqfR/1+z/tfxP/Fvj/mFX/0dD/7pz0fsR69p8rmHv20D9vl5mZ1flb67VkP81pT/8QPialmT1z/5f2QK/7v7Q/6Z/vb6F0DvToXzuf1PvDv4Nn/4s4+mujvzb6a6O/Nvpro782+mujvzb6a6O/Nvpro782+mujvzb6a6O/Nvpro782+mujvzb6a6O/tvg/UN4t6E9/+tO/d3+s1/8HUhSy6A==
</data> </data>
</layer> </layer>
<objectgroup id="1" name="PlayerStartingPos"> <objectgroup id="1" name="PlayerStartingPos">
<object id="135" x="1630" y="518"> <object id="135" x="1140" y="488">
<point/> <point/>
</object> </object>
<object id="137" x="888.003" y="535"> <object id="137" x="1527" y="488">
<point/> <point/>
</object> </object>
</objectgroup> </objectgroup>
@ -179,11 +179,6 @@
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="126" x="720" y="480" width="16" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="127" x="1088" y="320" width="16" height="16"> <object id="127" x="1088" y="320" width="16" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
@ -209,10 +204,5 @@
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="134" x="720" y="416" width="16" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
</objectgroup> </objectgroup>
</map> </map>

View File

@ -24,11 +24,11 @@
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 6 "__id__": 7
} }
], ],
"_prefab": { "_prefab": {
"__id__": 7 "__id__": 8
}, },
"_opacity": 255, "_opacity": 255,
"_color": { "_color": {
@ -79,23 +79,20 @@
}, },
{ {
"__type__": "cc.Node", "__type__": "cc.Node",
"_name": "Fireball1", "_name": "animNode",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 1 "__id__": 1
}, },
"_children": [], "_children": [
"_active": false,
"_components": [
{ {
"__id__": 3 "__id__": 3
},
{
"__id__": 4
} }
], ],
"_active": true,
"_components": [],
"_prefab": { "_prefab": {
"__id__": 5 "__id__": 6
}, },
"_opacity": 255, "_opacity": 255,
"_color": { "_color": {
@ -145,20 +142,67 @@
"_id": "" "_id": ""
}, },
{ {
"__type__": "cc.Animation", "__type__": "cc.Node",
"_name": "", "_name": "Fireball1",
"_objFlags": 0, "_objFlags": 0,
"node": { "_parent": {
"__id__": 2 "__id__": 2
}, },
"_enabled": true, "_children": [],
"_defaultClip": null, "_active": true,
"_clips": [ "_components": [
{ {
"__uuid__": "ba12416b-eec3-4260-8402-7fc25b125624" "__id__": 4
} }
], ],
"playOnLoad": false, "_prefab": {
"__id__": 5
},
"_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": "" "_id": ""
}, },
{ {
@ -166,13 +210,19 @@
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 2 "__id__": 3
}, },
"_enabled": true, "_enabled": true,
"_materials": [], "_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_srcBlendFactor": 770, "_srcBlendFactor": 770,
"_dstBlendFactor": 771, "_dstBlendFactor": 771,
"_spriteFrame": null, "_spriteFrame": {
"__uuid__": "e92702d5-d5fd-49e6-ab6b-2296b43fa6d6"
},
"_type": 0, "_type": 0,
"_sizeMode": 1, "_sizeMode": 1,
"_fillType": 0, "_fillType": 0,
@ -197,7 +247,18 @@
"asset": { "asset": {
"__uuid__": "d92d4831-cd65-4eb5-90bd-b77021aec35b" "__uuid__": "d92d4831-cd65-4eb5-90bd-b77021aec35b"
}, },
"fileId": "9ds3kDxvVFFqyr760jrV4a", "fileId": "5f1s6pDt5F3rknJTu0gQW7",
"sync": false
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__uuid__": "d92d4831-cd65-4eb5-90bd-b77021aec35b"
},
"fileId": "3824oBeVVL1KOAQ6Zd9CC5",
"sync": false "sync": false
}, },
{ {
@ -208,6 +269,9 @@
"__id__": 1 "__id__": 1
}, },
"_enabled": true, "_enabled": true,
"animNode": {
"__id__": 2
},
"_id": "" "_id": ""
}, },
{ {

View File

@ -440,7 +440,7 @@
"array": [ "array": [
0, 0,
0, 0,
216.50635094610968, 215.94663282292512,
0, 0,
0, 0,
0, 0,

View File

@ -191,8 +191,8 @@
0, 0,
0, 0,
1, 1,
1.2, 0.8,
1.2, 0.8,
1 1
] ]
}, },
@ -464,7 +464,7 @@
"array": [ "array": [
0, 0,
0, 0,
209.57814771583418, 215.64032554232523,
0, 0,
0, 0,
0, 0,

View File

@ -29,9 +29,6 @@ cc.Class({
if (!selfPlayerRichInfo) return; if (!selfPlayerRichInfo) return;
const selfPlayerNode = selfPlayerRichInfo.node; const selfPlayerNode = selfPlayerRichInfo.node;
if (!selfPlayerNode) return; if (!selfPlayerNode) return;
const pDiff = selfPlayerNode.position.sub(self.mainCamera.node.position); self.mapNode.setPosition(cc.v2().sub(selfPlayerNode.position));
pDiff.normalizeSelf();
const newCamPos = self.mainCamera.node.position.add(pDiff.mul(dt*self.speed));
self.mainCamera.node.setPosition(newCamPos);
} }
}); });

View File

@ -1,6 +1,13 @@
cc.Class({ cc.Class({
extends: cc.Component, extends: cc.Component,
properties: {
animNode: {
type: cc.Node,
default: null
},
},
ctor() { ctor() {
this.lastUsed = -1; this.lastUsed = -1;
this.bulletLocalId = -1; this.bulletLocalId = -1;
@ -9,28 +16,30 @@ cc.Class({
setSpecies(speciesName, fireballBullet, rdf) { setSpecies(speciesName, fireballBullet, rdf) {
if (speciesName == this.speciesName) return; if (speciesName == this.speciesName) return;
this.speciesName = speciesName; if (null != this.speciesName) {
this.effAnimNode = this.node.getChildByName(this.speciesName); for (let k in this.animNode.children) {
this.animComp = this.effAnimNode.getComponent(cc.Animation);
this.effAnimNode.active = true;
for (let k in this.children) {
const child = this.children[k]; const child = this.children[k];
if (!child.active) continue; if (!child.active) continue;
if (child == effAnimNode || child.name == speciesName) continue; if (child == effAnimNode || child.name == speciesName) continue;
child.active = false; child.active = false;
} }
this.updateAnim(speciesName, fireballBullet, rdf); }
this.speciesName = speciesName;
this.effAnimNode = this.animNode.getChildByName(this.speciesName);
this.effAnimNode.active = true;
//this.updateAnim(speciesName, fireballBullet, rdf);
}, },
onLoad() {}, onLoad() {},
updateAnim(speciesName, fireballBullet, rdf) { updateAnim(speciesName, fireballBullet, rdf) {
this.animComp = this.effAnimNode.getComponent(cc.Animation);
// Update directions // Update directions
if (this.animComp && this.animComp.node) { if (this.animComp && this.animComp.node) {
if (0 > fireballBullet.DirX) { if (0 > fireballBullet.DirX) {
this.effAnimNode.scaleX = (-1.0); this.animNode.scaleX = (-1.0);
} else if (0 < fireballBullet.DirX) { } else if (0 < fireballBullet.DirX) {
this.effAnimNode.scaleX = (1.0); this.animNode.scaleX = (1.0);
} }
} }

View File

@ -413,7 +413,7 @@ cc.Class({
window.mapIns = self; window.mapIns = self;
window.forceBigEndianFloatingNumDecoding = self.forceBigEndianFloatingNumDecoding; window.forceBigEndianFloatingNumDecoding = self.forceBigEndianFloatingNumDecoding;
self.showCriticalCoordinateLabels = true; self.showCriticalCoordinateLabels = false;
console.warn("+++++++ Map onLoad()"); console.warn("+++++++ Map onLoad()");
@ -1095,23 +1095,6 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
_renderFireballBullet(fireballBullet, rdf) { _renderFireballBullet(fireballBullet, rdf) {
const self = this; const self = this;
let pqNode = self.cachedFireballs.popAny(fireballBullet.Bullet.BulletLocalId);
const speciesName = `Fireball${fireballBullet.SpeciesId}`;
if (null == pqNode) {
pqNode = self.cachedFireballs.pop();
} else {
console.log(`Using a cached fireball node for rendering for bulletLocalId=${fireballBullet.Bullet.BulletLocalId}`);
}
const cachedFireball = pqNode.value;
cachedFireball.setSpecies(speciesName, fireballBullet, rdf);
cachedFireball.lastUsed = self.renderFrameId;
cachedFireball.bulletLocalId = fireballBullet.Bullet.BulletLocalId;
const [wx, wy] = gopkgs.VirtualGridToWorldPos(fireballBullet.VirtualGridX, fireballBullet.VirtualGridY);
cachedFireball.node.setPosition(cc.v2(wx, wy));
self.cachedFireballs.push(cachedFireball.lastUsed, cachedFireball, cachedFireball.bulletLocalId);
}, },
applyRoomDownsyncFrameDynamics(rdf, prevRdf) { applyRoomDownsyncFrameDynamics(rdf, prevRdf) {
@ -1137,8 +1120,28 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
const fireballBullets = rdf.FireballBullets; const fireballBullets = rdf.FireballBullets;
for (let k in fireballBullets) { for (let k in fireballBullets) {
const fireballBullet = fireballBullets[k]; const fireballBullet = fireballBullets[k];
if ((fireballBullet.Bullet.OriginatedRenderFrameId + fireballBullet.Bullet.StartupFrames <= rdf.Id) && (fireballBullet.Bullet.OriginatedRenderFrameId + fireballBullet.Bullet.StartupFrames + fireballBullet.Bullet.ActiveFrames > rdf.Id)) { if (
self._renderFireballBullet(fireballBullet, rdf); fireballBullet.Bullet.OriginatedRenderFrameId + fireballBullet.Bullet.StartupFrames <= rdf.Id
&&
fireballBullet.Bullet.OriginatedRenderFrameId + fireballBullet.Bullet.StartupFrames + fireballBullet.Bullet.ActiveFrames > rdf.Id
) {
let pqNode = self.cachedFireballs.popAny(fireballBullet.Bullet.BulletLocalId);
const speciesName = `Fireball${fireballBullet.SpeciesId}`;
const [wx, wy] = gopkgs.VirtualGridToWorldPos(fireballBullet.VirtualGridX, fireballBullet.VirtualGridY);
if (null == pqNode) {
pqNode = self.cachedFireballs.pop();
console.log(`@rdf.Id=${rdf.Id}, origRdfId=${fireballBullet.Bullet.OriginatedRenderFrameId}, startupFrames=${fireballBullet.Bullet.StartupFrames}, activeFrames=${fireballBullet.Bullet.ActiveFrames}, using a new fireball node for rendering for bulletLocalId=${fireballBullet.Bullet.BulletLocalId} at wpos=(${wx},${wy})`);
} else {
console.log(`@rdf.Id=${rdf.Id}, origRdfId=${fireballBullet.Bullet.OriginatedRenderFrameId}, startupFrames=${fireballBullet.Bullet.StartupFrames}, activeFrames=${fireballBullet.Bullet.ActiveFrames}, using a cached fireball node for rendering for bulletLocalId=${fireballBullet.Bullet.BulletLocalId} at wpos=(${wx},${wy})`);
}
const cachedFireball = pqNode.value;
cachedFireball.setSpecies(speciesName, fireballBullet, rdf);
cachedFireball.lastUsed = self.renderFrameId;
cachedFireball.bulletLocalId = fireballBullet.Bullet.BulletLocalId;
cachedFireball.node.setPosition(cc.v2(wx, wy));
self.cachedFireballs.push(cachedFireball.lastUsed, cachedFireball, fireballBullet.Bullet.BulletLocalId);
} }
} }
@ -1263,7 +1266,12 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
playerDownsyncStr(playerDownsync) { playerDownsyncStr(playerDownsync) {
if (null == playerDownsync) return ""; 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.Bullet.BulletLocalId},${fireball.Bullet.OriginatedRenderFrameId},${fireball.Bullet.OffenderJoinIndex},${fireball.VirtualGridX},${fireball.VirtualGridY},${fireball.VelX},${fireball.VelY},${fireball.DirX},${fireball.DirY},${fireball.Bullet.HitboxSizeX},${fireball.Bullet.HitboxSizeY}}`;
}, },
inputFrameDownsyncStr(inputFrameDownsync) { inputFrameDownsyncStr(inputFrameDownsync) {
@ -1292,8 +1300,13 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
for (let k in rdf.PlayersArr) { for (let k in rdf.PlayersArr) {
playersStrBldr.push(self.playerDownsyncStr(rdf.PlayersArr[k])); 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} s.push(`rdfId:${i}
players:[${playersStrBldr.join(',')}] players:[${playersStrBldr.join(',')}]
fireballs:[${fireballsStrBldr.join(',')}]
actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`); actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`);
} }

View File

@ -94,7 +94,7 @@ cc.Class({
const p2Vpos = gopkgs.WorldToVirtualGridPos(boundaryObjs.playerStartingPositions[1].x, boundaryObjs.playerStartingPositions[1].y); const p2Vpos = gopkgs.WorldToVirtualGridPos(boundaryObjs.playerStartingPositions[1].x, boundaryObjs.playerStartingPositions[1].y);
const colliderRadiusV = gopkgs.WorldToVirtualGridPos(12.0, 0); const colliderRadiusV = gopkgs.WorldToVirtualGridPos(12.0, 0);
const speciesIdList = [1, 4096]; const speciesIdList = [4096, 1];
const chConfigsOrderedByJoinIndex = gopkgs.GetCharacterConfigsOrderedByJoinIndex(speciesIdList); const chConfigsOrderedByJoinIndex = gopkgs.GetCharacterConfigsOrderedByJoinIndex(speciesIdList);
const startRdf = window.pb.protos.RoomDownsyncFrame.create({ const startRdf = window.pb.protos.RoomDownsyncFrame.create({

View File

@ -3,6 +3,7 @@ package battle
import ( import (
"math" "math"
"resolv" "resolv"
//"fmt"
) )
const ( const (
@ -21,7 +22,7 @@ const (
GRAVITY_X = int32(0) GRAVITY_X = int32(0)
GRAVITY_Y = -int32(float64(0.5) * WORLD_TO_VIRTUAL_GRID_RATIO) // makes all "playerCollider.Y" a multiple of 0.5 in all cases GRAVITY_Y = -int32(float64(0.5) * WORLD_TO_VIRTUAL_GRID_RATIO) // makes all "playerCollider.Y" a multiple of 0.5 in all cases
INPUT_DELAY_FRAMES = int32(8) // in the count of render frames INPUT_DELAY_FRAMES = int32(4) // in the count of render frames
INPUT_SCALE_FRAMES = uint32(2) // inputDelayedAndScaledFrameId = ((originalFrameId - InputDelayFrames) >> InputScaleFrames) INPUT_SCALE_FRAMES = uint32(2) // inputDelayedAndScaledFrameId = ((originalFrameId - InputDelayFrames) >> InputScaleFrames)
NST_DELAY_FRAMES = int32(16) // network-single-trip delay in the count of render frames, proposed to be (InputDelayFrames >> 1) because we expect a round-trip delay to be exactly "InputDelayFrames" NST_DELAY_FRAMES = int32(16) // network-single-trip delay in the count of render frames, proposed to be (InputDelayFrames >> 1) because we expect a round-trip delay to be exactly "InputDelayFrames"
@ -509,6 +510,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
} }
} }
// [WARNING] For rollback compatibility, MeleeBullets are composed of only static BulletConfig data and move along with the offenders, therefore they can just be copies of the pointers in "RenderFrameBuffer", however, FireballBullets move on their own and must be copies of instances for each RenderFrame!
nextRenderFrameMeleeBullets := make([]*MeleeBullet, 0, len(currRenderFrame.MeleeBullets)) // Is there any better way to reduce malloc/free impact, e.g. smart prediction for fixed memory allocation? nextRenderFrameMeleeBullets := make([]*MeleeBullet, 0, len(currRenderFrame.MeleeBullets)) // Is there any better way to reduce malloc/free impact, e.g. smart prediction for fixed memory allocation?
nextRenderFrameFireballBullets := make([]*FireballBullet, 0, len(currRenderFrame.FireballBullets)) nextRenderFrameFireballBullets := make([]*FireballBullet, 0, len(currRenderFrame.FireballBullets))
effPushbacks := make([]Vec2D, roomCapacity) effPushbacks := make([]Vec2D, roomCapacity)
@ -539,38 +541,39 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
switch v := skillConfig.Hits[thatPlayerInNextFrame.ActiveSkillHit].(type) { switch v := skillConfig.Hits[thatPlayerInNextFrame.ActiveSkillHit].(type) {
case *MeleeBullet: case *MeleeBullet:
var newBullet MeleeBullet = *v // Copied primitive fields into an onstack variable var newBullet MeleeBullet = *v // Copied primitive fields into an onstack variable
newBullet.BulletLocalId = bulletLocalId newBullet.Bullet.BulletLocalId = bulletLocalId
bulletLocalId++ bulletLocalId++
newBullet.OriginatedRenderFrameId = currRenderFrame.Id newBullet.Bullet.OriginatedRenderFrameId = currRenderFrame.Id
newBullet.OffenderJoinIndex = joinIndex newBullet.Bullet.OffenderJoinIndex = joinIndex
nextRenderFrameMeleeBullets = append(nextRenderFrameMeleeBullets, &newBullet) nextRenderFrameMeleeBullets = append(nextRenderFrameMeleeBullets, &newBullet)
if NO_LOCK_VEL != v.SelfLockVelX { if NO_LOCK_VEL != v.Bullet.SelfLockVelX {
hasLockVel = true 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 hasLockVel = true
thatPlayerInNextFrame.VelY = v.SelfLockVelY thatPlayerInNextFrame.VelY = v.Bullet.SelfLockVelY
} }
case *FireballBullet: case *FireballBullet:
var newBullet FireballBullet = *v // Copied primitive fields into an onstack variable var newBullet FireballBullet = *v // Copied primitive fields into an onstack variable
newBullet.BulletLocalId = bulletLocalId newBullet.Bullet.BulletLocalId = bulletLocalId
bulletLocalId++ bulletLocalId++
newBullet.VirtualGridX, newBullet.VirtualGridY = currPlayerDownsync.VirtualGridX+xfac*newBullet.HitboxOffsetX, currPlayerDownsync.VirtualGridY+newBullet.HitboxOffsetY newBullet.Bullet.OriginatedRenderFrameId = currRenderFrame.Id
newBullet.OriginatedRenderFrameId = currRenderFrame.Id newBullet.Bullet.OffenderJoinIndex = joinIndex
newBullet.OffenderJoinIndex = joinIndex newBullet.VirtualGridX, newBullet.VirtualGridY = currPlayerDownsync.VirtualGridX+xfac*newBullet.Bullet.HitboxOffsetX, currPlayerDownsync.VirtualGridY+newBullet.Bullet.HitboxOffsetY
newBullet.DirX = xfac newBullet.DirX = xfac
newBullet.DirY = 0 newBullet.DirY = 0
newBullet.VelX = newBullet.Speed * xfac newBullet.VelX = newBullet.Speed * xfac
newBullet.VelY = 0 newBullet.VelY = 0
nextRenderFrameFireballBullets = append(nextRenderFrameFireballBullets, &newBullet) 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 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 hasLockVel = true
thatPlayerInNextFrame.VelY = v.SelfLockVelY thatPlayerInNextFrame.VelY = v.Bullet.SelfLockVelY
} }
} }
@ -666,31 +669,43 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
// 3. Add bullet colliders into collision system // 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 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 { for _, meleeBullet := range currRenderFrame.MeleeBullets {
if (meleeBullet.OriginatedRenderFrameId+meleeBullet.StartupFrames <= currRenderFrame.Id) && (meleeBullet.OriginatedRenderFrameId+meleeBullet.StartupFrames+meleeBullet.ActiveFrames > currRenderFrame.Id) { if (meleeBullet.Bullet.OriginatedRenderFrameId+meleeBullet.Bullet.StartupFrames <= currRenderFrame.Id) && (meleeBullet.Bullet.OriginatedRenderFrameId+meleeBullet.Bullet.StartupFrames+meleeBullet.Bullet.ActiveFrames > currRenderFrame.Id) {
offender := currRenderFrame.PlayersArr[meleeBullet.OffenderJoinIndex-1] offender := currRenderFrame.PlayersArr[meleeBullet.Bullet.OffenderJoinIndex-1]
xfac := int32(1) // By now, straight Punch offset doesn't respect "y-axis" xfac := int32(1) // By now, straight Punch offset doesn't respect "y-axis"
if 0 > offender.DirX { if 0 > offender.DirX {
xfac = -xfac xfac = -xfac
} }
bulletWx, bulletWy := VirtualGridToWorldPos(offender.VirtualGridX+xfac*meleeBullet.HitboxOffsetX, offender.VirtualGridY) bulletWx, bulletWy := VirtualGridToWorldPos(offender.VirtualGridX+xfac*meleeBullet.Bullet.HitboxOffsetX, offender.VirtualGridY)
hitboxSizeWx, hitboxSizeWy := VirtualGridToWorldPos(meleeBullet.HitboxSizeX, meleeBullet.HitboxSizeY) 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") 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) collisionSys.Add(newBulletCollider)
bulletColliders = append(bulletColliders, newBulletCollider) bulletColliders = append(bulletColliders, newBulletCollider)
} else if meleeBullet.OriginatedRenderFrameId+meleeBullet.StartupFrames+meleeBullet.ActiveFrames > currRenderFrame.Id { } else if meleeBullet.Bullet.OriginatedRenderFrameId+meleeBullet.Bullet.StartupFrames+meleeBullet.Bullet.ActiveFrames > currRenderFrame.Id {
nextRenderFrameMeleeBullets = append(nextRenderFrameMeleeBullets, meleeBullet) nextRenderFrameMeleeBullets = append(nextRenderFrameMeleeBullets, meleeBullet)
} }
} }
for _, fireballBullet := range currRenderFrame.FireballBullets { for _, prevFireball := range currRenderFrame.FireballBullets {
if (fireballBullet.OriginatedRenderFrameId+fireballBullet.StartupFrames < currRenderFrame.Id) && (fireballBullet.OriginatedRenderFrameId+fireballBullet.StartupFrames+fireballBullet.ActiveFrames > currRenderFrame.Id) { fireballBullet := &FireballBullet{
VirtualGridX: prevFireball.VirtualGridX,
VirtualGridY: prevFireball.VirtualGridY,
DirX: prevFireball.DirX,
DirY: prevFireball.DirY,
VelX: prevFireball.VelX,
VelY: prevFireball.VelY,
Speed: prevFireball.Speed,
SpeciesId: prevFireball.SpeciesId,
Bullet: prevFireball.Bullet,
}
if (fireballBullet.Bullet.OriginatedRenderFrameId+fireballBullet.Bullet.StartupFrames < currRenderFrame.Id) && (fireballBullet.Bullet.OriginatedRenderFrameId+fireballBullet.Bullet.StartupFrames+fireballBullet.Bullet.ActiveFrames > currRenderFrame.Id) {
bulletWx, bulletWy := VirtualGridToWorldPos(fireballBullet.VirtualGridX, fireballBullet.VirtualGridY) bulletWx, bulletWy := VirtualGridToWorldPos(fireballBullet.VirtualGridX, fireballBullet.VirtualGridY)
hitboxSizeWx, hitboxSizeWy := VirtualGridToWorldPos(fireballBullet.HitboxSizeX, fireballBullet.HitboxSizeY) 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") 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) collisionSys.Add(newBulletCollider)
bulletColliders = append(bulletColliders, newBulletCollider) bulletColliders = append(bulletColliders, newBulletCollider)
} else if fireballBullet.OriginatedRenderFrameId+fireballBullet.StartupFrames+fireballBullet.ActiveFrames > currRenderFrame.Id { } else if fireballBullet.Bullet.OriginatedRenderFrameId+fireballBullet.Bullet.StartupFrames+fireballBullet.Bullet.ActiveFrames > currRenderFrame.Id {
// fmt.Printf("Pushing static fireball to next frame @currRenderFrame.Id=%d, bulletLocalId=%d, virtualGridX=%d, virtualGridY=%d\n", currRenderFrame.Id, fireballBullet.BulletLocalId, fireballBullet.VirtualGridX, fireballBullet.VirtualGridY)
nextRenderFrameFireballBullets = append(nextRenderFrameFireballBullets, fireballBullet) nextRenderFrameFireballBullets = append(nextRenderFrameFireballBullets, fireballBullet)
} }
} }
@ -828,12 +843,12 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
switch v := bulletCollider.Data.(type) { switch v := bulletCollider.Data.(type) {
case *MeleeBullet: case *MeleeBullet:
bulletShape := bulletCollider.Shape.(*resolv.ConvexPolygon) bulletShape := bulletCollider.Shape.(*resolv.ConvexPolygon)
offender := currRenderFrame.PlayersArr[v.OffenderJoinIndex-1] offender := currRenderFrame.PlayersArr[v.Bullet.OffenderJoinIndex-1]
for _, obj := range collision.Objects { for _, obj := range collision.Objects {
defenderShape := obj.Shape.(*resolv.ConvexPolygon) defenderShape := obj.Shape.(*resolv.ConvexPolygon)
switch t := obj.Data.(type) { switch t := obj.Data.(type) {
case *PlayerDownsync: case *PlayerDownsync:
if v.OffenderJoinIndex == t.JoinIndex { if v.Bullet.OffenderJoinIndex == t.JoinIndex {
continue continue
} }
overlapped, _, _, _ := calcPushbacks(0, 0, bulletShape, defenderShape) overlapped, _, _, _ := calcPushbacks(0, 0, bulletShape, defenderShape)
@ -851,18 +866,18 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
if 0 > offender.DirX { if 0 > offender.DirX {
xfac = -xfac xfac = -xfac
} }
pushbackVelX, pushbackVelY := xfac*v.PushbackVelX, v.PushbackVelY pushbackVelX, pushbackVelY := xfac*v.Bullet.PushbackVelX, v.Bullet.PushbackVelY
atkedPlayerInNextFrame := nextRenderFramePlayers[t.JoinIndex-1] atkedPlayerInNextFrame := nextRenderFramePlayers[t.JoinIndex-1]
atkedPlayerInNextFrame.VelX = pushbackVelX atkedPlayerInNextFrame.VelX = pushbackVelX
atkedPlayerInNextFrame.VelY = pushbackVelY atkedPlayerInNextFrame.VelY = pushbackVelY
if v.BlowUp { if v.Bullet.BlowUp {
atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_BLOWN_UP1 atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_BLOWN_UP1
} else { } else {
atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_ATKED1 atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_ATKED1
} }
oldFramesToRecover := nextRenderFramePlayers[t.JoinIndex-1].FramesToRecover oldFramesToRecover := nextRenderFramePlayers[t.JoinIndex-1].FramesToRecover
if v.HitStunFrames > oldFramesToRecover { if v.Bullet.HitStunFrames > oldFramesToRecover {
atkedPlayerInNextFrame.FramesToRecover = v.HitStunFrames atkedPlayerInNextFrame.FramesToRecover = v.Bullet.HitStunFrames
} }
default: default:
addToNextRenderFrame = false addToNextRenderFrame = false
@ -870,12 +885,12 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
} }
case *FireballBullet: case *FireballBullet:
bulletShape := bulletCollider.Shape.(*resolv.ConvexPolygon) bulletShape := bulletCollider.Shape.(*resolv.ConvexPolygon)
offender := currRenderFrame.PlayersArr[v.OffenderJoinIndex-1] offender := currRenderFrame.PlayersArr[v.Bullet.OffenderJoinIndex-1]
for _, obj := range collision.Objects { for _, obj := range collision.Objects {
defenderShape := obj.Shape.(*resolv.ConvexPolygon) defenderShape := obj.Shape.(*resolv.ConvexPolygon)
switch t := obj.Data.(type) { switch t := obj.Data.(type) {
case *PlayerDownsync: case *PlayerDownsync:
if v.OffenderJoinIndex == t.JoinIndex { if v.Bullet.OffenderJoinIndex == t.JoinIndex {
continue continue
} }
overlapped, _, _, _ := calcPushbacks(0, 0, bulletShape, defenderShape) overlapped, _, _, _ := calcPushbacks(0, 0, bulletShape, defenderShape)
@ -893,18 +908,18 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
if 0 > offender.DirX { if 0 > offender.DirX {
xfac = -xfac xfac = -xfac
} }
pushbackVelX, pushbackVelY := xfac*v.PushbackVelX, v.PushbackVelY pushbackVelX, pushbackVelY := xfac*v.Bullet.PushbackVelX, v.Bullet.PushbackVelY
atkedPlayerInNextFrame := nextRenderFramePlayers[t.JoinIndex-1] atkedPlayerInNextFrame := nextRenderFramePlayers[t.JoinIndex-1]
atkedPlayerInNextFrame.VelX = pushbackVelX atkedPlayerInNextFrame.VelX = pushbackVelX
atkedPlayerInNextFrame.VelY = pushbackVelY atkedPlayerInNextFrame.VelY = pushbackVelY
if v.BlowUp { if v.Bullet.BlowUp {
atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_BLOWN_UP1 atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_BLOWN_UP1
} else { } else {
atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_ATKED1 atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_ATKED1
} }
oldFramesToRecover := nextRenderFramePlayers[t.JoinIndex-1].FramesToRecover oldFramesToRecover := nextRenderFramePlayers[t.JoinIndex-1].FramesToRecover
if v.HitStunFrames > oldFramesToRecover { if v.Bullet.HitStunFrames > oldFramesToRecover {
atkedPlayerInNextFrame.FramesToRecover = v.HitStunFrames atkedPlayerInNextFrame.FramesToRecover = v.Bullet.HitStunFrames
} }
default: default:
addToNextRenderFrame = false addToNextRenderFrame = false
@ -1053,3 +1068,77 @@ func AlignPolygon2DToBoundingBox(input *Polygon2D) *Polygon2D {
return output 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 int32) *MeleeBullet {
return &MeleeBullet{
Bullet: &BulletConfig{
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 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, speciesId int32) *FireballBullet {
return &FireballBullet{
VirtualGridX: virtualGridX,
VirtualGridY: virtualGridY,
DirX: dirX,
DirY: dirY,
VelX: velX,
VelY: velY,
Speed: speed,
SpeciesId: speciesId,
Bullet: &BulletConfig{
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,
},
}
}

View File

@ -61,8 +61,8 @@ var Characters = map[int]*CharacterConfig{
if skillConfig, existent1 := skills[int(currPlayerDownsync.ActiveSkillId)]; existent1 { if skillConfig, existent1 := skills[int(currPlayerDownsync.ActiveSkillId)]; existent1 {
switch v := skillConfig.Hits[currPlayerDownsync.ActiveSkillHit].(type) { switch v := skillConfig.Hits[currPlayerDownsync.ActiveSkillHit].(type) {
case *MeleeBullet: case *MeleeBullet:
if v.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.CancellableEdFrame { if v.Bullet.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.Bullet.CancellableEdFrame {
if nextSkillId, existent2 := v.CancelTransit[patternId]; existent2 { if nextSkillId, existent2 := v.Bullet.CancelTransit[patternId]; existent2 {
return nextSkillId return nextSkillId
} }
} }
@ -111,8 +111,8 @@ var Characters = map[int]*CharacterConfig{
if skillConfig, existent1 := skills[int(currPlayerDownsync.ActiveSkillId)]; existent1 { if skillConfig, existent1 := skills[int(currPlayerDownsync.ActiveSkillId)]; existent1 {
switch v := skillConfig.Hits[currPlayerDownsync.ActiveSkillHit].(type) { switch v := skillConfig.Hits[currPlayerDownsync.ActiveSkillHit].(type) {
case *MeleeBullet: case *MeleeBullet:
if v.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.CancellableEdFrame { if v.Bullet.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.Bullet.CancellableEdFrame {
if nextSkillId, existent2 := v.CancelTransit[patternId]; existent2 { if nextSkillId, existent2 := v.Bullet.CancelTransit[patternId]; existent2 {
return nextSkillId return nextSkillId
} }
} }
@ -157,8 +157,8 @@ var Characters = map[int]*CharacterConfig{
if skillConfig, existent1 := skills[int(currPlayerDownsync.ActiveSkillId)]; existent1 { if skillConfig, existent1 := skills[int(currPlayerDownsync.ActiveSkillId)]; existent1 {
switch v := skillConfig.Hits[currPlayerDownsync.ActiveSkillHit].(type) { switch v := skillConfig.Hits[currPlayerDownsync.ActiveSkillHit].(type) {
case *MeleeBullet: case *MeleeBullet:
if v.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.CancellableEdFrame { if v.Bullet.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.Bullet.CancellableEdFrame {
if nextSkillId, existent2 := v.CancelTransit[patternId]; existent2 { if nextSkillId, existent2 := v.Bullet.CancelTransit[patternId]; existent2 {
return nextSkillId return nextSkillId
} }
} }
@ -190,7 +190,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK1, BoundChState: ATK_CHARACTER_STATE_ATK1,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(7), StartupFrames: int32(7),
ActiveFrames: int32(22), ActiveFrames: int32(22),
HitStunFrames: int32(13), HitStunFrames: int32(13),
@ -223,7 +223,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK2, BoundChState: ATK_CHARACTER_STATE_ATK2,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(18), StartupFrames: int32(18),
ActiveFrames: int32(18), ActiveFrames: int32(18),
HitStunFrames: int32(18), HitStunFrames: int32(18),
@ -254,7 +254,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK3, BoundChState: ATK_CHARACTER_STATE_ATK3,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(8), StartupFrames: int32(8),
ActiveFrames: int32(30), ActiveFrames: int32(30),
HitStunFrames: MAX_INT32, HitStunFrames: MAX_INT32,
@ -281,7 +281,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK1, BoundChState: ATK_CHARACTER_STATE_ATK1,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(7), StartupFrames: int32(7),
ActiveFrames: int32(22), ActiveFrames: int32(22),
HitStunFrames: int32(13), HitStunFrames: int32(13),
@ -314,7 +314,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK2, BoundChState: ATK_CHARACTER_STATE_ATK2,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(18), StartupFrames: int32(18),
ActiveFrames: int32(18), ActiveFrames: int32(18),
HitStunFrames: int32(18), HitStunFrames: int32(18),
@ -345,7 +345,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK3, BoundChState: ATK_CHARACTER_STATE_ATK3,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(8), StartupFrames: int32(8),
ActiveFrames: int32(28), ActiveFrames: int32(28),
HitStunFrames: MAX_INT32, HitStunFrames: MAX_INT32,
@ -372,7 +372,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK1, BoundChState: ATK_CHARACTER_STATE_ATK1,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(7), StartupFrames: int32(7),
ActiveFrames: int32(22), ActiveFrames: int32(22),
HitStunFrames: int32(13), HitStunFrames: int32(13),
@ -405,7 +405,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK2, BoundChState: ATK_CHARACTER_STATE_ATK2,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(18), StartupFrames: int32(18),
ActiveFrames: int32(18), ActiveFrames: int32(18),
HitStunFrames: int32(18), HitStunFrames: int32(18),
@ -436,7 +436,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK3, BoundChState: ATK_CHARACTER_STATE_ATK3,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(7), StartupFrames: int32(7),
ActiveFrames: int32(30), ActiveFrames: int32(30),
HitStunFrames: MAX_INT32, HitStunFrames: MAX_INT32,
@ -464,8 +464,8 @@ var skills = map[int]*Skill{
Hits: []interface{}{ Hits: []interface{}{
&FireballBullet{ &FireballBullet{
SpeciesId: int32(1), SpeciesId: int32(1),
Speed: int32(float64(8) * WORLD_TO_VIRTUAL_GRID_RATIO), Speed: int32(float64(5) * WORLD_TO_VIRTUAL_GRID_RATIO),
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(15), StartupFrames: int32(15),
ActiveFrames: MAX_INT32, ActiveFrames: MAX_INT32,
HitStunFrames: int32(15), HitStunFrames: int32(15),
@ -475,7 +475,7 @@ var skills = map[int]*Skill{
SelfLockVelY: NO_LOCK_VEL, SelfLockVelY: NO_LOCK_VEL,
PushbackVelX: int32(float64(2) * WORLD_TO_VIRTUAL_GRID_RATIO), PushbackVelX: int32(float64(2) * WORLD_TO_VIRTUAL_GRID_RATIO),
PushbackVelY: int32(0), PushbackVelY: int32(0),
HitboxOffsetX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxOffsetX: int32(float64(18) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetY: int32(float64(5) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxOffsetY: int32(float64(5) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeX: int32(float64(48) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxSizeX: int32(float64(48) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeY: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxSizeY: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
@ -491,7 +491,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK5, BoundChState: ATK_CHARACTER_STATE_ATK5,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(3), StartupFrames: int32(3),
ActiveFrames: int32(25), ActiveFrames: int32(25),
HitStunFrames: MAX_INT32, HitStunFrames: MAX_INT32,
@ -518,7 +518,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1, BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(3), StartupFrames: int32(3),
ActiveFrames: int32(20), ActiveFrames: int32(20),
HitStunFrames: int32(18), HitStunFrames: int32(18),
@ -544,7 +544,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1, BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(3), StartupFrames: int32(3),
ActiveFrames: int32(10), ActiveFrames: int32(10),
HitStunFrames: int32(15), HitStunFrames: int32(15),
@ -570,7 +570,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1, BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(3), StartupFrames: int32(3),
ActiveFrames: int32(20), ActiveFrames: int32(20),
HitStunFrames: int32(18), HitStunFrames: int32(18),

View File

@ -34,6 +34,8 @@ type PlayerDownsync struct {
CharacterState int32 CharacterState int32
InAir bool InAir bool
OnWall bool OnWall bool
OnWallNormX int32
OnWallNormY int32
ActiveSkillId int32 ActiveSkillId int32
ActiveSkillHit int32 ActiveSkillHit int32
@ -42,9 +44,6 @@ type PlayerDownsync struct {
BulletTeamId int32 BulletTeamId int32
ChCollisionTeamId int32 // not the same as "BulletTeamId", because even in the same team, we should allow inter-character collisions ChCollisionTeamId int32 // not the same as "BulletTeamId", because even in the same team, we should allow inter-character collisions
OnWallNormX int32
OnWallNormY int32
} }
type InputFrameDecoded struct { type InputFrameDecoded struct {
@ -63,7 +62,7 @@ type Barrier struct {
Boundary *Polygon2D Boundary *Polygon2D
} }
type Bullet struct { type BulletConfig struct {
BulletLocalId int32 // for referencing cached nodes in frontend rendering BulletLocalId int32 // for referencing cached nodes in frontend rendering
// for offender // for offender
@ -97,7 +96,7 @@ type Bullet struct {
} }
type MeleeBullet struct { type MeleeBullet struct {
Bullet Bullet *BulletConfig
} }
type FireballBullet struct { type FireballBullet struct {
@ -109,7 +108,7 @@ type FireballBullet struct {
VelY int32 VelY int32
Speed int32 Speed int32
SpeciesId int32 SpeciesId int32
Bullet Bullet *BulletConfig
} }
type Skill struct { type Skill struct {

View File

@ -73,77 +73,11 @@ func NewPlayerDownsyncJs(id, virtualGridX, virtualGridY, dirX, dirY, velX, velY,
} }
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 { 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{ return js.MakeWrapper(NewMeleeBullet(bulletLocalId, originatedRenderFrameId, offenderJoinIndex, startupFrames, cancellableStFrame, cancellableEdFrame, activeFrames, hitStunFrames, blockStunFrames, pushbackVelX, pushbackVelY, damage, selfLockVelX, selfLockVelY, hitboxOffsetX, hitboxOffsetY, hitboxSizeX, hitboxSizeY, blowUp, teamId))
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, speciesId int32) *js.Object { 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, speciesId int32) *js.Object {
return js.MakeWrapper(&FireballBullet{ 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, speciesId))
VirtualGridX: virtualGridX,
VirtualGridY: virtualGridY,
DirX: dirX,
DirY: dirY,
VelX: velX,
VelY: velY,
Speed: speed,
SpeciesId: speciesId,
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 NewNpcPatrolCue(flAct, frAct uint64, x, y float64) *js.Object { func NewNpcPatrolCue(flAct, frAct uint64, x, y float64) *js.Object {