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

@ -1,37 +1,34 @@
cc.Class({ cc.Class({
extends: cc.Component, extends: cc.Component,
properties: { properties: {
mapNode: { mapNode: {
type: cc.Node, type: cc.Node,
default: null default: null
},
speed: {
type: cc.Float,
default: 500
},
}, },
speed: {
onLoad () { type: cc.Float,
this.mainCamera = this.mapNode.parent.getChildByName("Main Camera").getComponent(cc.Camera); default: 500
this.mapScriptIns = this.mapNode.getComponent("Map");
}, },
},
start() {}, onLoad() {
this.mainCamera = this.mapNode.parent.getChildByName("Main Camera").getComponent(cc.Camera);
this.mapScriptIns = this.mapNode.getComponent("Map");
},
update(dt) { start() {},
const self = this;
if (!self.mainCamera) return; update(dt) {
if (!self.mapScriptIns) return; const self = this;
if (!self.mapScriptIns.selfPlayerInfo) return; if (!self.mainCamera) return;
if (!self.mapScriptIns.playerRichInfoDict) return; if (!self.mapScriptIns) return;
const selfPlayerRichInfo = self.mapScriptIns.playerRichInfoDict.get(self.mapScriptIns.selfPlayerInfo.Id); if (!self.mapScriptIns.selfPlayerInfo) return;
if (!selfPlayerRichInfo) return; if (!self.mapScriptIns.playerRichInfoDict) return;
const selfPlayerNode = selfPlayerRichInfo.node; const selfPlayerRichInfo = self.mapScriptIns.playerRichInfoDict.get(self.mapScriptIns.selfPlayerInfo.Id);
if (!selfPlayerNode) return; if (!selfPlayerRichInfo) return;
const pDiff = selfPlayerNode.position.sub(self.mainCamera.node.position); const selfPlayerNode = selfPlayerRichInfo.node;
pDiff.normalizeSelf(); if (!selfPlayerNode) return;
const newCamPos = self.mainCamera.node.position.add(pDiff.mul(dt*self.speed)); self.mapNode.setPosition(cc.v2().sub(selfPlayerNode.position));
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); const child = this.children[k];
this.effAnimNode.active = true; if (!child.active) continue;
for (let k in this.children) { if (child == effAnimNode || child.name == speciesName) continue;
const child = this.children[k]; child.active = false;
if (!child.active) continue; }
if (child == effAnimNode || child.name == speciesName) continue;
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"
@ -360,22 +361,22 @@ func VirtualGridToPolygonColliderBLPos(vx, vy int32, halfBoundingW, halfBounding
func calcHardPushbacksNorms(joinIndex int32, currPlayerDownsync, thatPlayerInNextFrame *PlayerDownsync, 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 ret := make([]Vec2D, 0, 10) // no one would simultaneously have more than 5 hardPushbacks
virtualGripToWall := float64(0) virtualGripToWall := float64(0)
if ATK_CHARACTER_STATE_ONWALL == currPlayerDownsync.CharacterState && 0 == thatPlayerInNextFrame.VelX && currPlayerDownsync.DirX == thatPlayerInNextFrame.DirX { 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. 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 The workaround here is to grant a "virtualGripToWall" in x-axis to guarantee that if
- "currPlayerDownsync" is on wall, and - "currPlayerDownsync" is on wall, and
- "thatPlayerInNextFrame.VelX" is 0 (i.e. no proactive move against the wall), and - "thatPlayerInNextFrame.VelX" is 0 (i.e. no proactive move against the wall), and
- there's no change in player facing direction - there's no change in player facing direction
*/ */
xfac := float64(1) xfac := float64(1)
if 0 > thatPlayerInNextFrame.DirX { if 0 > thatPlayerInNextFrame.DirX {
xfac = -xfac xfac = -xfac
} }
virtualGripToWall = xfac*float64(currPlayerDownsync.Speed)*VIRTUAL_GRID_TO_WORLD_RATIO virtualGripToWall = xfac * float64(currPlayerDownsync.Speed) * VIRTUAL_GRID_TO_WORLD_RATIO
} }
collision := playerCollider.Check(virtualGripToWall, 0) collision := playerCollider.Check(virtualGripToWall, 0)
if nil == collision { if nil == collision {
return &ret return &ret
@ -498,8 +499,8 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
ActiveSkillHit: currPlayerDownsync.ActiveSkillHit, ActiveSkillHit: currPlayerDownsync.ActiveSkillHit,
FramesInvinsible: currPlayerDownsync.FramesInvinsible - 1, FramesInvinsible: currPlayerDownsync.FramesInvinsible - 1,
ColliderRadius: currPlayerDownsync.ColliderRadius, ColliderRadius: currPlayerDownsync.ColliderRadius,
OnWallNormX: currPlayerDownsync.OnWallNormX, OnWallNormX: currPlayerDownsync.OnWallNormX,
OnWallNormY: currPlayerDownsync.OnWallNormY, OnWallNormY: currPlayerDownsync.OnWallNormY,
} }
if nextRenderFramePlayers[i].FramesToRecover < 0 { if nextRenderFramePlayers[i].FramesToRecover < 0 {
nextRenderFramePlayers[i].FramesToRecover = 0 nextRenderFramePlayers[i].FramesToRecover = 0
@ -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
} }
} }
@ -616,12 +619,12 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
if jumpedOrNotList[i] { if jumpedOrNotList[i] {
// We haven't proceeded with "OnWall" calculation for "thatPlayerInNextFrame", thus use "currPlayerDownsync.OnWall" for checking // We haven't proceeded with "OnWall" calculation for "thatPlayerInNextFrame", thus use "currPlayerDownsync.OnWall" for checking
if ATK_CHARACTER_STATE_ONWALL == currPlayerDownsync.CharacterState { if ATK_CHARACTER_STATE_ONWALL == currPlayerDownsync.CharacterState {
if 0 < currPlayerDownsync.VelX * currPlayerDownsync.OnWallNormX { if 0 < currPlayerDownsync.VelX*currPlayerDownsync.OnWallNormX {
newVx -= currPlayerDownsync.VelX // Cancel the alleged horizontal movement pointing to same direction of wall inward norm first newVx -= currPlayerDownsync.VelX // Cancel the alleged horizontal movement pointing to same direction of wall inward norm first
} }
xfac := int32(-1) xfac := int32(-1)
if 0 > currPlayerDownsync.OnWallNormX { if 0 > currPlayerDownsync.OnWallNormX {
// Always jump to the opposite direction of wall inward norm // Always jump to the opposite direction of wall inward norm
xfac = -xfac xfac = -xfac
} }
newVx += xfac * chConfig.WallJumpingInitVelX newVx += xfac * chConfig.WallJumpingInitVelX
@ -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)
} }
} }
@ -786,36 +801,36 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
} }
} }
if chConfig.OnWallEnabled { if chConfig.OnWallEnabled {
if thatPlayerInNextFrame.InAir { if thatPlayerInNextFrame.InAir {
// [WARNING] Sticking to wall MUST BE based on "InAir", otherwise we would get gravity reduction from ground up incorrectly! // [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 { if _, existent := noOpSet[currPlayerDownsync.CharacterState]; !existent {
// [WARNING] Sticking to wall could only be triggered by proactive player input // [WARNING] Sticking to wall could only be triggered by proactive player input
for _, hardPushbackNorm := range *hardPushbackNorms[joinIndex-1] { for _, hardPushbackNorm := range *hardPushbackNorms[joinIndex-1] {
normAlignmentWithHorizon1 := (hardPushbackNorm.X*float64(1.0) + hardPushbackNorm.Y*float64(0.0)) normAlignmentWithHorizon1 := (hardPushbackNorm.X*float64(1.0) + hardPushbackNorm.Y*float64(0.0))
normAlignmentWithHorizon2 := (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 { if VERTICAL_PLATFORM_THRESHOLD < normAlignmentWithHorizon1 {
thatPlayerInNextFrame.OnWall = true thatPlayerInNextFrame.OnWall = true
thatPlayerInNextFrame.OnWallNormX, thatPlayerInNextFrame.OnWallNormY = int32(hardPushbackNorm.X), int32(hardPushbackNorm.Y) thatPlayerInNextFrame.OnWallNormX, thatPlayerInNextFrame.OnWallNormY = int32(hardPushbackNorm.X), int32(hardPushbackNorm.Y)
break break
} }
if VERTICAL_PLATFORM_THRESHOLD < normAlignmentWithHorizon2 { if VERTICAL_PLATFORM_THRESHOLD < normAlignmentWithHorizon2 {
thatPlayerInNextFrame.OnWall = true thatPlayerInNextFrame.OnWall = true
thatPlayerInNextFrame.OnWallNormX, thatPlayerInNextFrame.OnWallNormY = int32(hardPushbackNorm.X), int32(hardPushbackNorm.Y) thatPlayerInNextFrame.OnWallNormX, thatPlayerInNextFrame.OnWallNormY = int32(hardPushbackNorm.X), int32(hardPushbackNorm.Y)
break break
} }
} }
if !currPlayerDownsync.OnWall && thatPlayerInNextFrame.OnWall { if !currPlayerDownsync.OnWall && thatPlayerInNextFrame.OnWall {
// To avoid mysterious climbing up the wall after sticking on it // To avoid mysterious climbing up the wall after sticking on it
thatPlayerInNextFrame.VelY = 0 thatPlayerInNextFrame.VelY = 0
} }
} }
} }
if !thatPlayerInNextFrame.OnWall { if !thatPlayerInNextFrame.OnWall {
thatPlayerInNextFrame.OnWallNormX, thatPlayerInNextFrame.OnWallNormY = 0, 0 thatPlayerInNextFrame.OnWallNormX, thatPlayerInNextFrame.OnWallNormY = 0, 0
} }
} }
} }
@ -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
} }
} }
@ -93,7 +93,7 @@ var Characters = map[int]*CharacterConfig{
DashingEnabled: true, DashingEnabled: true,
OnWallEnabled: true, OnWallEnabled: true,
WallJumpingFramesToRecover: int32(9), // 8 would be the minimum for an avg human WallJumpingFramesToRecover: int32(9), // 8 would be the minimum for an avg human
WallJumpingInitVelX: int32(float64(2.5) * WORLD_TO_VIRTUAL_GRID_RATIO), // Default is "appeared facing right", but actually holding ctrl against left WallJumpingInitVelX: int32(float64(2.5) * 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), WallJumpingInitVelY: int32(float64(7) * WORLD_TO_VIRTUAL_GRID_RATIO),
WallSlidingVelY: int32(float64(-1) * WORLD_TO_VIRTUAL_GRID_RATIO), WallSlidingVelY: int32(float64(-1) * WORLD_TO_VIRTUAL_GRID_RATIO),
@ -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

@ -65,85 +65,19 @@ func NewPlayerDownsyncJs(id, virtualGridX, virtualGridY, dirX, dirY, velX, velY,
ColliderRadius: colliderRadius, ColliderRadius: colliderRadius,
InAir: inAir, InAir: inAir,
OnWall: onWall, OnWall: onWall,
OnWallNormX: onWallNormX, OnWallNormX: onWallNormX,
OnWallNormY: onWallNormY, OnWallNormY: onWallNormY,
BulletTeamId: bulletTeamId, BulletTeamId: bulletTeamId,
ChCollisionTeamId: chCollisionTeamId, 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 { 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 {