mirror of
https://github.com/RandomityGuy/MBHaxe.git
synced 2025-10-30 08:11:25 +00:00
gems and player list
This commit is contained in:
parent
17e77c7096
commit
ff5f6e1a9b
14 changed files with 460 additions and 59 deletions
|
|
@ -2163,9 +2163,9 @@ class Marble extends GameObject {
|
|||
this.blastPerc = amount;
|
||||
var impulse = this.currentUp.multiply(amount * 8);
|
||||
this.applyImpulse(impulse);
|
||||
if (this.controllable)
|
||||
AudioManager.playSound(ResourceLoader.getResource('data/sound/use_blast.wav', ResourceLoader.getAudio, this.soundResources));
|
||||
if (!this.isNetUpdate) {
|
||||
if (this.controllable)
|
||||
AudioManager.playSound(ResourceLoader.getResource('data/sound/use_blast.wav', ResourceLoader.getAudio, this.soundResources));
|
||||
this.blastWave.doSequenceOnceBeginTime = this.level.timeState.timeSinceLoad;
|
||||
this.blastUseTime = this.level.timeState.currentAttemptTime;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package src;
|
||||
|
||||
import net.GemPredictionStore;
|
||||
import modes.HuntMode;
|
||||
import net.NetPacket.MarbleNetFlags;
|
||||
import net.PowerupPredictionStore;
|
||||
import net.MarblePredictionStore;
|
||||
|
|
@ -211,6 +213,7 @@ class MarbleWorld extends Scheduler {
|
|||
var clientMarbles:Map<GameConnection, Marble> = [];
|
||||
var predictions:MarblePredictionStore;
|
||||
var powerupPredictions:PowerupPredictionStore;
|
||||
var gemPredictions:GemPredictionStore;
|
||||
|
||||
public var lastMoves:MarbleUpdateQueue;
|
||||
|
||||
|
|
@ -254,6 +257,7 @@ class MarbleWorld extends Scheduler {
|
|||
lastMoves = new MarbleUpdateQueue();
|
||||
predictions = new MarblePredictionStore();
|
||||
powerupPredictions = new PowerupPredictionStore();
|
||||
gemPredictions = new GemPredictionStore();
|
||||
}
|
||||
|
||||
// Set the network RNG for hunt
|
||||
|
|
@ -333,6 +337,19 @@ class MarbleWorld extends Scheduler {
|
|||
this.collisionWorld.finalizeStaticGeometry();
|
||||
this.playGui.init(this.scene2d, this.mission.game.toLowerCase());
|
||||
this.scene.addChild(this.sky);
|
||||
|
||||
if (this.isMultiplayer) {
|
||||
// Add us
|
||||
if (Net.isHost) {
|
||||
this.playGui.addPlayer(0, 'Player 0', true);
|
||||
} else {
|
||||
this.playGui.addPlayer(Net.clientId, 'Player ${Net.clientId}', true);
|
||||
}
|
||||
for (client in Net.clientIdMap) {
|
||||
this.playGui.addPlayer(client.id, 'Player ${client.id}', false);
|
||||
}
|
||||
}
|
||||
|
||||
this._ready = true;
|
||||
// AudioManager.playShell();
|
||||
MarbleGame.canvas.clearContent();
|
||||
|
|
@ -1160,6 +1177,10 @@ class MarbleWorld extends Scheduler {
|
|||
// Console.log('Revert powerup pickup: ${pw.lastPickUpTime} -> ${val}');
|
||||
pw.lastPickUpTime = powerupPredictions.getState(pw.netIndex);
|
||||
}
|
||||
var huntMode:HuntMode = cast this.gameMode;
|
||||
for (activeGem in @:privateAccess huntMode.activeGemSpawnGroup) {
|
||||
huntMode.setGemHiddenStatus(activeGem, gemPredictions.getState(activeGem));
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
|
|
@ -1182,10 +1203,10 @@ class MarbleWorld extends Scheduler {
|
|||
Debug.drawSphere(@:privateAccess marbleToUpdate.newPos, marbleToUpdate._radius);
|
||||
|
||||
var distFromUs = @:privateAccess marbleToUpdate.newPos.distance(this.marble.newPos);
|
||||
if (distFromUs < 5)
|
||||
m.calculationTicks = ourQueuedMoves.length; // ourQueuedMoves.length;
|
||||
else
|
||||
m.calculationTicks = Std.int(Math.max(1, ourQueuedMoves.length - (distFromUs - 5) / 3));
|
||||
// if (distFromUs < 5)
|
||||
m.calculationTicks = ourQueuedMoves.length; // ourQueuedMoves.length;
|
||||
// else
|
||||
// m.calculationTicks = Std.int(Math.max(1, ourQueuedMoves.length - (distFromUs - 5) / 3));
|
||||
// - Std.int((@:privateAccess Net.clientConnection.moveManager.ackRTT - ourLastMove.moveQueueSize) / 2);
|
||||
|
||||
marblesToTick.set(client, m);
|
||||
|
|
@ -1233,6 +1254,14 @@ class MarbleWorld extends Scheduler {
|
|||
return -1;
|
||||
}
|
||||
|
||||
public function spawnHuntGemsClientSide(gemIds:Array<Int>) {
|
||||
if (this.isMultiplayer && Net.isClient) {
|
||||
var huntMode:HuntMode = cast this.gameMode;
|
||||
huntMode.setActiveSpawnSphere(gemIds);
|
||||
radar.blink();
|
||||
}
|
||||
}
|
||||
|
||||
public function rollback(t:Float) {
|
||||
var newT = timeState.currentAttemptTime - t;
|
||||
var rewindFrame = rewindManager.getNextRewindFrame(timeState.currentAttemptTime - t);
|
||||
|
|
|
|||
|
|
@ -342,6 +342,13 @@ class Util {
|
|||
'${(hours > 0 ? (hoursTen > 0 ? '${hoursTen}' : '') +'${hoursOne}' + ':' : '')}${minutesTen}${minutesOne}:${secondsTen}${secondsOne}.${hundredthTen}${hundredthOne}${thousandth}';
|
||||
}
|
||||
|
||||
public static function rightPad(str:String, len:Int, cutOff:Int) {
|
||||
str = str.substring(0, len - cutOff);
|
||||
while (str.length < len)
|
||||
str += " ";
|
||||
return str;
|
||||
}
|
||||
|
||||
public static function getKeyForButton(button:Int) {
|
||||
var keyName = Key.getKeyName(button);
|
||||
if (keyName == "MouseLeft")
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package gui;
|
||||
|
||||
import h2d.filter.Filter;
|
||||
import h2d.HtmlText;
|
||||
import h2d.Flow;
|
||||
import h3d.Engine;
|
||||
|
|
@ -33,14 +34,17 @@ class GuiMLTextListCtrl extends GuiControl {
|
|||
|
||||
public var scrollable:Bool = false;
|
||||
|
||||
var filter:Filter = null;
|
||||
|
||||
var flow:Flow;
|
||||
var _imageLoader:String->Tile;
|
||||
|
||||
public function new(font:Font, texts:Array<String>, imageLoader:String->Tile) {
|
||||
public function new(font:Font, texts:Array<String>, imageLoader:String->Tile, ?filter:Filter = null) {
|
||||
super();
|
||||
this.font = font;
|
||||
this.texts = texts;
|
||||
this.textObjs = [];
|
||||
this.filter = filter;
|
||||
this._imageLoader = imageLoader;
|
||||
for (text in texts) {
|
||||
var tobj = new HtmlText(font);
|
||||
|
|
@ -48,6 +52,8 @@ class GuiMLTextListCtrl extends GuiControl {
|
|||
tobj.loadImage = imageLoader;
|
||||
tobj.text = text;
|
||||
tobj.textColor = 0;
|
||||
if (filter != null)
|
||||
tobj.filter = filter;
|
||||
textObjs.push(tobj);
|
||||
}
|
||||
this.g = new Graphics();
|
||||
|
|
@ -65,6 +71,8 @@ class GuiMLTextListCtrl extends GuiControl {
|
|||
tobj.lineHeightMode = TextOnly;
|
||||
tobj.text = text;
|
||||
tobj.textColor = 0;
|
||||
if (filter != null)
|
||||
tobj.filter = filter;
|
||||
textObjs.push(tobj);
|
||||
|
||||
if (this.scrollable) {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ class GuiTextListCtrl extends GuiControl {
|
|||
|
||||
public var selectedColor:Int = 0x206464;
|
||||
public var selectedFillColor:Int = 0xC8C8C8;
|
||||
public var textColor:Int = 0;
|
||||
|
||||
public var textYOffset:Int = 0;
|
||||
|
||||
|
|
@ -34,15 +35,16 @@ class GuiTextListCtrl extends GuiControl {
|
|||
|
||||
var flow:Flow;
|
||||
|
||||
public function new(font:Font, texts:Array<String>) {
|
||||
public function new(font:Font, texts:Array<String>, textColor:Int = 0) {
|
||||
super();
|
||||
this.font = font;
|
||||
this.texts = texts;
|
||||
this.textObjs = [];
|
||||
this.textColor = textColor;
|
||||
for (text in texts) {
|
||||
var tobj = new Text(font);
|
||||
tobj.text = text;
|
||||
tobj.textColor = 0;
|
||||
tobj.textColor = textColor;
|
||||
textObjs.push(tobj);
|
||||
}
|
||||
this.g = new Graphics();
|
||||
|
|
@ -57,7 +59,7 @@ class GuiTextListCtrl extends GuiControl {
|
|||
for (text in texts) {
|
||||
var tobj = new Text(font);
|
||||
tobj.text = text;
|
||||
tobj.textColor = 0;
|
||||
tobj.textColor = textColor;
|
||||
textObjs.push(tobj);
|
||||
|
||||
if (this.scrollable) {
|
||||
|
|
@ -178,7 +180,7 @@ class GuiTextListCtrl extends GuiControl {
|
|||
for (i in 0...textObjs.length) {
|
||||
var selected = i == hoverIndex || i == this._prevSelected;
|
||||
var text = textObjs[i];
|
||||
text.textColor = selected ? selectedColor : 0;
|
||||
text.textColor = selected ? selectedColor : textColor;
|
||||
// fill color = 0xC8C8C8
|
||||
}
|
||||
// obviously in renderRect
|
||||
|
|
@ -189,7 +191,7 @@ class GuiTextListCtrl extends GuiControl {
|
|||
if (i == this._prevSelected)
|
||||
continue;
|
||||
var text = textObjs[i];
|
||||
text.textColor = 0;
|
||||
text.textColor = textColor;
|
||||
// fill color = 0xC8C8C8
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,13 @@ typedef MiddleMessage = {
|
|||
yPos:Float
|
||||
}
|
||||
|
||||
typedef PlayerInfo = {
|
||||
id:Int,
|
||||
name:String,
|
||||
us:Bool,
|
||||
score:Int
|
||||
}
|
||||
|
||||
class PlayGui {
|
||||
var scene2d:h2d.Scene;
|
||||
|
||||
|
|
@ -64,6 +71,12 @@ class PlayGui {
|
|||
var blastFillUltra:GuiImage;
|
||||
var blastFrame:GuiImage;
|
||||
|
||||
var playerListContainerOuter:GuiControl;
|
||||
var playerListContainer:GuiControl;
|
||||
var playerListCtrl:GuiMLTextListCtrl;
|
||||
var playerListScoresCtrl:GuiMLTextListCtrl;
|
||||
var playerList:Array<PlayerInfo> = [];
|
||||
|
||||
var imageResources:Array<Resource<Image>> = [];
|
||||
var textureResources:Array<Resource<Texture>> = [];
|
||||
var soundResources:Array<Resource<Sound>> = [];
|
||||
|
|
@ -137,11 +150,14 @@ class PlayGui {
|
|||
gemCountNumbers.push(new GuiAnim(numberTiles));
|
||||
}
|
||||
initTimer();
|
||||
initGemCounter();
|
||||
if (!MarbleGame.instance.world.isMultiplayer)
|
||||
initGemCounter();
|
||||
initPowerupBox();
|
||||
if (game == 'ultra')
|
||||
initBlastBar();
|
||||
initTexts();
|
||||
if (MarbleGame.instance.world.isMultiplayer)
|
||||
initPlayerList();
|
||||
|
||||
if (Util.isTouchDevice()) {
|
||||
MarbleGame.instance.touchInput.showControls(this.playGuiCtrlOuter, game == 'ultra');
|
||||
|
|
@ -574,6 +590,106 @@ class PlayGui {
|
|||
}
|
||||
}
|
||||
|
||||
function initPlayerList() {
|
||||
var arial14fontdata = ResourceLoader.getFileEntry("data/font/Arial Bold.fnt");
|
||||
var arial14b = new BitmapFont(arial14fontdata.entry);
|
||||
@:privateAccess arial14b.loader = ResourceLoader.loader;
|
||||
var arial14 = arial14b.toSdfFont(cast 22 * Settings.uiScale, MultiChannel);
|
||||
|
||||
var coliseumfontdata = ResourceLoader.getFileEntry("data/font/ColiseumRR.fnt");
|
||||
var coliseumb = new BitmapFont(coliseumfontdata.entry);
|
||||
@:privateAccess coliseumb.loader = ResourceLoader.loader;
|
||||
var coliseum = coliseumb.toSdfFont(cast 44 * Settings.uiScale, MultiChannel);
|
||||
|
||||
playerListContainer = new GuiControl();
|
||||
playerListContainer.horizSizing = Right;
|
||||
playerListContainer.vertSizing = Bottom;
|
||||
playerListContainer.position = new Vector(0, 0);
|
||||
playerListContainer.extent = new Vector(392, 360);
|
||||
this.playGuiCtrl.addChild(playerListContainer);
|
||||
|
||||
var scoreBackdrop = new GuiImage(ResourceLoader.getResource("data/ui/game/scoreBackdrop.png", ResourceLoader.getImage, this.imageResources).toTile());
|
||||
scoreBackdrop.position = new Vector(0, 0);
|
||||
scoreBackdrop.extent = new Vector(386, 128);
|
||||
playerListContainer.addChild(scoreBackdrop);
|
||||
|
||||
var scorePlusMinus = new GuiImage(ResourceLoader.getResource("data/ui/game/scoreBackdropMinus.png", ResourceLoader.getImage, this.imageResources)
|
||||
.toTile());
|
||||
scorePlusMinus.position = new Vector(20, 17);
|
||||
scorePlusMinus.extent = new Vector(22, 111);
|
||||
scoreBackdrop.addChild(scorePlusMinus);
|
||||
|
||||
function imgLoader(path:String) {
|
||||
switch (path) {
|
||||
case "us":
|
||||
return ResourceLoader.getResource("data/ui/xbox/GreenDot.png", ResourceLoader.getImage, this.imageResources).toTile();
|
||||
case "them":
|
||||
return ResourceLoader.getResource("data/ui/xbox/EmptyDot.png", ResourceLoader.getImage, this.imageResources).toTile();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// var playerList = [
|
||||
// '<font color="#EBEBEB"><img src="us"></img>Player 1 1</font>',
|
||||
// '<font color="#EBEBEB"><img src="them"></img>Player 2 2</font>'
|
||||
// ];
|
||||
|
||||
var ds = new h2d.filter.DropShadow(1.414, 0.785, 0x000000, 1, 0, 0.4, 1, true);
|
||||
|
||||
playerListCtrl = new GuiMLTextListCtrl(arial14, [], imgLoader, ds);
|
||||
|
||||
playerListCtrl.position = new Vector(27, 43);
|
||||
playerListCtrl.extent = new Vector(392, 271);
|
||||
playerListCtrl.scrollable = true;
|
||||
playerListCtrl.onSelectedFunc = (sel) -> {}
|
||||
playerListContainer.addChild(playerListCtrl);
|
||||
|
||||
playerListScoresCtrl = new GuiMLTextListCtrl(arial14, [], imgLoader, ds);
|
||||
|
||||
playerListScoresCtrl.position = new Vector(277, 43);
|
||||
playerListScoresCtrl.extent = new Vector(392, 271);
|
||||
playerListScoresCtrl.scrollable = true;
|
||||
playerListScoresCtrl.onSelectedFunc = (sel) -> {}
|
||||
playerListContainer.addChild(playerListScoresCtrl);
|
||||
}
|
||||
|
||||
public function redrawPlayerList() {
|
||||
var pl = [];
|
||||
var plScores = [];
|
||||
playerList.sort((a, b) -> a.score > b.score ? -1 : (a.score < b.score ? 1 : 0));
|
||||
for (item in playerList) {
|
||||
pl.push('<font color="#EBEBEB"><img src="${item.us ? "us" : "them"}"></img>${Util.rightPad(item.name, 25, 3)}</font>');
|
||||
plScores.push('<font color="#EBEBEB">${item.score}</font>');
|
||||
}
|
||||
playerListCtrl.setTexts(pl);
|
||||
playerListScoresCtrl.setTexts(plScores);
|
||||
}
|
||||
|
||||
public function addPlayer(id:Int, name:String, us:Bool) {
|
||||
playerList.push({
|
||||
id: id,
|
||||
name: name,
|
||||
us: us,
|
||||
score: 0
|
||||
});
|
||||
redrawPlayerList();
|
||||
}
|
||||
|
||||
public function removePlayer(id:Int) {
|
||||
var f = playerList.filter(x -> x.id == id);
|
||||
if (f.length != 0)
|
||||
playerList.remove(f[0]);
|
||||
redrawPlayerList();
|
||||
}
|
||||
|
||||
public function incrementPlayerScore(id:Int, score:Int) {
|
||||
var f = playerList.filter(x -> x.id == id);
|
||||
if (f.length != 0)
|
||||
f[0].score += score;
|
||||
|
||||
redrawPlayerList();
|
||||
}
|
||||
|
||||
public function setHelpTextOpacity(value:Float) {
|
||||
@:privateAccess helpTextForeground.text._textColorVec.a = value;
|
||||
@:privateAccess helpTextBackground.text._textColorVec.a = value;
|
||||
|
|
@ -702,6 +818,8 @@ class PlayGui {
|
|||
}
|
||||
|
||||
public function formatGemCounter(collected:Int, total:Int) {
|
||||
if (MarbleGame.instance.world.isMultiplayer)
|
||||
return;
|
||||
if (total == 0) {
|
||||
for (number in gemCountNumbers) {
|
||||
number.anim.visible = false;
|
||||
|
|
@ -734,6 +852,8 @@ class PlayGui {
|
|||
}
|
||||
|
||||
public function formatGemHuntCounter(collected:Int) {
|
||||
if (MarbleGame.instance.world.isMultiplayer)
|
||||
return;
|
||||
gemCountNumbers[0].anim.visible = true;
|
||||
gemCountNumbers[1].anim.visible = true;
|
||||
gemCountNumbers[2].anim.visible = true;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
package modes;
|
||||
|
||||
import net.NetCommands;
|
||||
import net.NetPacket.GemPickupPacket;
|
||||
import haxe.Exception;
|
||||
import net.BitStream.OutputBitStream;
|
||||
import net.NetPacket.GemSpawnPacket;
|
||||
import net.Net;
|
||||
import rewind.RewindManager;
|
||||
import hxd.Rand;
|
||||
import rewind.RewindableState;
|
||||
|
|
@ -26,6 +32,7 @@ import src.Marble;
|
|||
|
||||
@:publicFields
|
||||
class GemSpawnSphere {
|
||||
var netIndex:Int;
|
||||
var position:Vector;
|
||||
var rotation:Quat;
|
||||
var element:MissionElementSpawnSphere;
|
||||
|
|
@ -176,8 +183,14 @@ class HuntMode extends NullMode {
|
|||
playerSpawnPoints.push(spawnSphere);
|
||||
spawnPointTaken.push(false);
|
||||
}
|
||||
if (dbname == "gemspawnspheremarker")
|
||||
gemSpawnPoints.push(new GemSpawnSphere(spawnSphere));
|
||||
if (dbname == "gemspawnspheremarker") {
|
||||
var sphere = new GemSpawnSphere(spawnSphere);
|
||||
sphere.netIndex = gemSpawnPoints.length;
|
||||
gemSpawnPoints.push(sphere);
|
||||
if (level.isMultiplayer) {
|
||||
@:privateAccess level.gemPredictions.alloc();
|
||||
}
|
||||
}
|
||||
} else if (element._type == MissionElementType.SimGroup) {
|
||||
scanMission(cast element);
|
||||
}
|
||||
|
|
@ -271,42 +284,75 @@ class HuntMode extends NullMode {
|
|||
}
|
||||
|
||||
override function onRestart() {
|
||||
rng.setSeed(100);
|
||||
rng2.setSeed(100);
|
||||
if (Settings.optionsSettings.huntRandom) {
|
||||
rng.setSeed(cast Math.random() * 10000);
|
||||
rng2.setSeed(cast Math.random() * 10000);
|
||||
if (!this.level.isMultiplayer || Net.isHost) {
|
||||
rng.setSeed(100);
|
||||
rng2.setSeed(100);
|
||||
if (Settings.optionsSettings.huntRandom) {
|
||||
rng.setSeed(cast Math.random() * 10000);
|
||||
rng2.setSeed(cast Math.random() * 10000);
|
||||
}
|
||||
setupGems();
|
||||
}
|
||||
setupGems();
|
||||
points = 0;
|
||||
@:privateAccess level.playGui.formatGemHuntCounter(points);
|
||||
}
|
||||
|
||||
override function onGemPickup(marble:Marble, gem:Gem) {
|
||||
if (marble == level.marble)
|
||||
AudioManager.playSound(ResourceLoader.getResource('data/sound/gem_collect.wav', ResourceLoader.getAudio,
|
||||
@:privateAccess this.level.soundResources));
|
||||
else
|
||||
AudioManager.playSound(ResourceLoader.getResource('data/sound/opponent_gem_collect.wav', ResourceLoader.getAudio,
|
||||
@:privateAccess this.level.soundResources));
|
||||
if (@:privateAccess !marble.isNetUpdate) {
|
||||
if (marble == level.marble)
|
||||
AudioManager.playSound(ResourceLoader.getResource('data/sound/gem_collect.wav', ResourceLoader.getAudio,
|
||||
@:privateAccess this.level.soundResources));
|
||||
else
|
||||
AudioManager.playSound(ResourceLoader.getResource('data/sound/opponent_gem_collect.wav', ResourceLoader.getAudio,
|
||||
@:privateAccess this.level.soundResources));
|
||||
}
|
||||
activeGems.remove(gem);
|
||||
var beam = gemToBeamMap.get(gem);
|
||||
beam.setHide(true);
|
||||
refillGemGroups();
|
||||
|
||||
if (marble == level.marble) {
|
||||
switch (gem.gemColor) {
|
||||
case "red.gem":
|
||||
points += 1;
|
||||
@:privateAccess level.playGui.addMiddleMessage('+1', 0xFF6666);
|
||||
case "yellow.gem":
|
||||
points += 2;
|
||||
@:privateAccess level.playGui.addMiddleMessage('+2', 0xFFFF66);
|
||||
case "blue.gem":
|
||||
points += 5;
|
||||
@:privateAccess level.playGui.addMiddleMessage('+5', 0x6666FF);
|
||||
if (!this.level.isMultiplayer || Net.isHost) {
|
||||
refillGemGroups();
|
||||
}
|
||||
|
||||
var incr = 0;
|
||||
switch (gem.gemColor) {
|
||||
case "red.gem":
|
||||
incr = 1;
|
||||
case "yellow.gem":
|
||||
incr = 2;
|
||||
case "blue.gem":
|
||||
incr = 5;
|
||||
}
|
||||
|
||||
if (@:privateAccess !marble.isNetUpdate) {
|
||||
if (marble == level.marble) {
|
||||
switch (gem.gemColor) {
|
||||
case "red.gem":
|
||||
points += 1;
|
||||
@:privateAccess level.playGui.addMiddleMessage('+1', 0xFF6666);
|
||||
case "yellow.gem":
|
||||
points += 2;
|
||||
@:privateAccess level.playGui.addMiddleMessage('+2', 0xFFFF66);
|
||||
case "blue.gem":
|
||||
points += 5;
|
||||
@:privateAccess level.playGui.addMiddleMessage('+5', 0x6666FF);
|
||||
}
|
||||
@:privateAccess level.playGui.formatGemHuntCounter(points);
|
||||
}
|
||||
@:privateAccess level.playGui.formatGemHuntCounter(points);
|
||||
}
|
||||
|
||||
if (this.level.isMultiplayer && Net.isHost) {
|
||||
var packet = new GemPickupPacket();
|
||||
packet.clientId = @:privateAccess marble.connection == null ? 0 : @:privateAccess marble.connection.id;
|
||||
packet.gemId = gem.netIndex;
|
||||
packet.serverTicks = level.timeState.ticks;
|
||||
packet.scoreIncr = incr;
|
||||
var os = new OutputBitStream();
|
||||
os.writeByte(GemPickup);
|
||||
packet.serialize(os);
|
||||
Net.sendPacketToAll(os);
|
||||
|
||||
@:privateAccess level.playGui.incrementPlayerScore(packet.clientId, packet.scoreIncr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -369,6 +415,15 @@ class HuntMode extends NullMode {
|
|||
activeGemSpawnGroup = spawnGroup;
|
||||
fillGemGroup(spawnGroup);
|
||||
@:privateAccess level.radar.blink();
|
||||
|
||||
if (level.isMultiplayer && Net.isHost) {
|
||||
var bs = new OutputBitStream();
|
||||
bs.writeByte(GemSpawn);
|
||||
var packet = new GemSpawnPacket();
|
||||
packet.gemIds = spawnGroup;
|
||||
packet.serialize(bs);
|
||||
Net.sendPacketToAll(bs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -384,6 +439,7 @@ class HuntMode extends NullMode {
|
|||
var melem = new MissionElementItem();
|
||||
melem.datablock = "GemItem" + gemSpawn.gemColor;
|
||||
var gem = new Gem(melem);
|
||||
gem.netIndex = gi;
|
||||
gemSpawn.gem = gem;
|
||||
gem.setPosition(gemSpawn.position.x, gemSpawn.position.y, gemSpawn.position.z);
|
||||
gem.setRotationQuat(gemSpawn.rotation);
|
||||
|
|
@ -406,6 +462,57 @@ class HuntMode extends NullMode {
|
|||
}
|
||||
}
|
||||
|
||||
public function setActiveSpawnSphere(spawnGroup:Array<Int>) {
|
||||
for (sphereId in spawnGroup) {
|
||||
var gemSpawn = gemSpawnPoints[sphereId];
|
||||
if (gemSpawn.gem != null) {
|
||||
gemSpawn.gem.pickedUp = false;
|
||||
gemSpawn.gem.setHide(false);
|
||||
gemSpawn.gemBeam.setHide(false);
|
||||
this.activeGems.push(gemSpawn.gem);
|
||||
} else {
|
||||
var melem = new MissionElementItem();
|
||||
melem.datablock = "GemItem" + gemSpawn.gemColor;
|
||||
var gem = new Gem(melem);
|
||||
gem.netIndex = sphereId;
|
||||
gemSpawn.gem = gem;
|
||||
gem.setPosition(gemSpawn.position.x, gemSpawn.position.y, gemSpawn.position.z);
|
||||
gem.setRotationQuat(gemSpawn.rotation);
|
||||
this.activeGems.push(gem);
|
||||
|
||||
var gemBeam = new GemBeam();
|
||||
gemBeam.setPosition(gemSpawn.position.x, gemSpawn.position.y, gemSpawn.position.z);
|
||||
gemBeam.setRotationQuat(gemSpawn.rotation);
|
||||
this.gemBeams.push(gemBeam);
|
||||
|
||||
gemSpawn.gemBeam = gemBeam;
|
||||
this.gemToBeamMap.set(gem, gemBeam);
|
||||
|
||||
level.addDtsObject(gemBeam, () -> {
|
||||
level.addDtsObject(gem, () -> {
|
||||
level.gems.push(gem);
|
||||
}); // Please be fast lol
|
||||
});
|
||||
}
|
||||
}
|
||||
activeGemSpawnGroup = spawnGroup;
|
||||
}
|
||||
|
||||
public inline function setGemHiddenStatus(gemId:Int, status:Bool) {
|
||||
var gemSpawn = gemSpawnPoints[gemId];
|
||||
if (gemSpawn.gem != null) {
|
||||
gemSpawn.gem.pickedUp = status;
|
||||
gemSpawn.gem.setHide(status);
|
||||
gemSpawn.gemBeam.setHide(status);
|
||||
if (status)
|
||||
this.activeGems.push(gemSpawn.gem);
|
||||
else
|
||||
this.activeGems.remove(gemSpawn.gem);
|
||||
} else {
|
||||
throw new Exception("Setting gem status for non existent gem!");
|
||||
}
|
||||
}
|
||||
|
||||
function pickGemSpawnGroup() {
|
||||
var searchRadius = gemGroupRadius * 2;
|
||||
|
||||
|
|
@ -477,6 +584,45 @@ class HuntMode extends NullMode {
|
|||
override function onTimeExpire() {
|
||||
if (level.finishTime != null)
|
||||
return;
|
||||
if (!this.level.isMultiplayer || Net.isHost) {
|
||||
AudioManager.playSound(ResourceLoader.getResource('data/sound/finish.wav', ResourceLoader.getAudio, @:privateAccess level.soundResources));
|
||||
level.finishTime = level.timeState.clone();
|
||||
level.marble.setMode(Start);
|
||||
level.marble.camera.finish = true;
|
||||
level.finishYaw = level.marble.camera.CameraYaw;
|
||||
level.finishPitch = level.marble.camera.CameraPitch;
|
||||
level.displayAlert("Congratulations! You've finished!");
|
||||
level.cancel(@:privateAccess level.oobSchedule);
|
||||
level.cancel(@:privateAccess level.marble.oobSchedule);
|
||||
if (Net.isHost) {
|
||||
NetCommands.timerRanOut();
|
||||
}
|
||||
if (!level.isWatching) {
|
||||
var myScore = {
|
||||
name: "Player",
|
||||
time: getFinishScore()
|
||||
};
|
||||
Settings.saveScore(level.mission.path, myScore, getScoreType());
|
||||
var notifies = AchievementsGui.check();
|
||||
var delay = 5.0;
|
||||
var achDelay = 0.0;
|
||||
for (i in 0...9) {
|
||||
if (notifies & (1 << i) > 0)
|
||||
achDelay += 3;
|
||||
}
|
||||
if (notifies > 0)
|
||||
achDelay += 0.5;
|
||||
@:privateAccess level.schedule(level.timeState.currentAttemptTime + Math.max(delay, achDelay), () -> cast level.showFinishScreen());
|
||||
}
|
||||
// Stop the ongoing sounds
|
||||
if (@:privateAccess level.timeTravelSound != null) {
|
||||
@:privateAccess level.timeTravelSound.stop();
|
||||
@:privateAccess level.timeTravelSound = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function doTimerRunOut() {
|
||||
AudioManager.playSound(ResourceLoader.getResource('data/sound/finish.wav', ResourceLoader.getAudio, @:privateAccess level.soundResources));
|
||||
level.finishTime = level.timeState.clone();
|
||||
level.marble.setMode(Start);
|
||||
|
|
@ -484,24 +630,8 @@ class HuntMode extends NullMode {
|
|||
level.finishYaw = level.marble.camera.CameraYaw;
|
||||
level.finishPitch = level.marble.camera.CameraPitch;
|
||||
level.displayAlert("Congratulations! You've finished!");
|
||||
level.cancel(@:privateAccess level.oobSchedule);
|
||||
level.cancel(@:privateAccess level.marble.oobSchedule);
|
||||
if (!level.isWatching) {
|
||||
var myScore = {
|
||||
name: "Player",
|
||||
time: getFinishScore()
|
||||
};
|
||||
Settings.saveScore(level.mission.path, myScore, getScoreType());
|
||||
var notifies = AchievementsGui.check();
|
||||
var delay = 5.0;
|
||||
var achDelay = 0.0;
|
||||
for (i in 0...9) {
|
||||
if (notifies & (1 << i) > 0)
|
||||
achDelay += 3;
|
||||
}
|
||||
if (notifies > 0)
|
||||
achDelay += 0.5;
|
||||
@:privateAccess level.schedule(level.timeState.currentAttemptTime + Math.max(delay, achDelay), () -> cast level.showFinishScreen());
|
||||
@:privateAccess level.schedule(level.timeState.currentAttemptTime, () -> cast level.showFinishScreen());
|
||||
}
|
||||
// Stop the ongoing sounds
|
||||
if (@:privateAccess level.timeTravelSound != null) {
|
||||
|
|
|
|||
29
src/net/GemPredictionStore.hx
Normal file
29
src/net/GemPredictionStore.hx
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package net;
|
||||
|
||||
import net.NetPacket.GemSpawnPacket;
|
||||
import net.NetPacket.GemPickupPacket;
|
||||
|
||||
class GemPredictionStore {
|
||||
var predictions:Array<Bool>;
|
||||
|
||||
public function new() {
|
||||
predictions = [];
|
||||
}
|
||||
|
||||
public function alloc() {
|
||||
predictions.push(true);
|
||||
}
|
||||
|
||||
public inline function getState(netIndex:Int) {
|
||||
return predictions[netIndex];
|
||||
}
|
||||
|
||||
public function acknowledgeGemPickup(packet:GemPickupPacket) {
|
||||
predictions[packet.gemId] = true;
|
||||
}
|
||||
|
||||
public function acknowledgeGemSpawn(packet:GemSpawnPacket) {
|
||||
for (gemId in packet.gemIds)
|
||||
predictions[gemId] = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -30,7 +30,7 @@ class MarblePrediction {
|
|||
if (p.netFlags != 0)
|
||||
subs += 1;
|
||||
// if (p.powerUpId != powerupItemId)
|
||||
// subs += 1;
|
||||
subs += 1; // temp
|
||||
// if (isControl)
|
||||
// subs += Math.abs(blastAmount - p.blastAmount);
|
||||
return subs;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package net;
|
||||
|
||||
import hl.I64;
|
||||
import net.NetPacket.MarbleNetFlags;
|
||||
import net.NetPacket.MarbleUpdatePacket;
|
||||
import net.Net;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package net;
|
||||
|
||||
import net.NetPacket.GemPickupPacket;
|
||||
import net.NetPacket.GemSpawnPacket;
|
||||
import net.BitStream.InputBitStream;
|
||||
import net.BitStream.OutputBitStream;
|
||||
import net.NetPacket.PowerupPickupPacket;
|
||||
|
|
@ -24,6 +26,8 @@ enum abstract NetPacketType(Int) from Int to Int {
|
|||
var MarbleUpdate;
|
||||
var MarbleMove;
|
||||
var PowerupPickup;
|
||||
var GemSpawn;
|
||||
var GemPickup;
|
||||
var PlayerInfo;
|
||||
}
|
||||
|
||||
|
|
@ -262,6 +266,22 @@ class Net {
|
|||
m.acknowledgePowerupPickup(powerupPickupPacket, MarbleGame.instance.world.timeState, clientConnection.moveManager.getQueueSize());
|
||||
}
|
||||
|
||||
case GemSpawn:
|
||||
var gemSpawnPacket = new GemSpawnPacket();
|
||||
gemSpawnPacket.deserialize(input);
|
||||
if (MarbleGame.instance.world != null) {
|
||||
MarbleGame.instance.world.spawnHuntGemsClientSide(gemSpawnPacket.gemIds);
|
||||
@:privateAccess MarbleGame.instance.world.gemPredictions.acknowledgeGemSpawn(gemSpawnPacket);
|
||||
}
|
||||
|
||||
case GemPickup:
|
||||
var gemPickupPacket = new GemPickupPacket();
|
||||
gemPickupPacket.deserialize(input);
|
||||
if (MarbleGame.instance.world != null) {
|
||||
@:privateAccess MarbleGame.instance.world.playGui.incrementPlayerScore(gemPickupPacket.clientId, gemPickupPacket.scoreIncr);
|
||||
@:privateAccess MarbleGame.instance.world.gemPredictions.acknowledgeGemPickup(gemPickupPacket);
|
||||
}
|
||||
|
||||
case PlayerInfo:
|
||||
var count = input.readByte();
|
||||
for (i in 0...count) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package net;
|
||||
|
||||
import modes.HuntMode;
|
||||
import net.ClientConnection.GameplayState;
|
||||
import net.Net.NetPacketType;
|
||||
import gui.MultiplayerLevelSelectGui;
|
||||
|
|
@ -51,4 +52,11 @@ class NetCommands {
|
|||
MarbleGame.instance.world.startRealTime = MarbleGame.instance.world.timeState.timeSinceLoad + t;
|
||||
}
|
||||
}
|
||||
|
||||
@:rpc(server) public static function timerRanOut() {
|
||||
if (Net.isClient && MarbleGame.instance.world != null) {
|
||||
var huntMode:HuntMode = cast MarbleGame.instance.world.gameMode;
|
||||
huntMode.onTimeExpire();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,3 +152,50 @@ class PowerupPickupPacket implements NetPacket {
|
|||
b.writeInt(powerupItemId, 9);
|
||||
}
|
||||
}
|
||||
|
||||
@:publicFields
|
||||
class GemSpawnPacket implements NetPacket {
|
||||
var gemIds:Array<Int>;
|
||||
|
||||
public function new() {
|
||||
gemIds = [];
|
||||
}
|
||||
|
||||
public function serialize(b:OutputBitStream) {
|
||||
b.writeInt(gemIds.length, 5);
|
||||
for (gemId in gemIds) {
|
||||
b.writeInt(gemId, 10);
|
||||
}
|
||||
}
|
||||
|
||||
public function deserialize(b:InputBitStream) {
|
||||
var count = b.readInt(5);
|
||||
for (i in 0...count) {
|
||||
gemIds.push(b.readInt(10));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@:publicFields
|
||||
class GemPickupPacket implements NetPacket {
|
||||
var clientId:Int;
|
||||
var serverTicks:Int;
|
||||
var gemId:Int;
|
||||
var scoreIncr:Int;
|
||||
|
||||
public function new() {}
|
||||
|
||||
public inline function deserialize(b:InputBitStream) {
|
||||
clientId = b.readByte();
|
||||
serverTicks = b.readUInt16();
|
||||
gemId = b.readInt(10);
|
||||
scoreIncr = b.readInt(4);
|
||||
}
|
||||
|
||||
public inline function serialize(b:OutputBitStream) {
|
||||
b.writeByte(clientId);
|
||||
b.writeUInt16(serverTicks);
|
||||
b.writeInt(gemId, 10);
|
||||
b.writeInt(scoreIncr, 4);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import src.Marble;
|
|||
class Gem extends DtsObject {
|
||||
public var pickedUp:Bool;
|
||||
|
||||
public var netIndex:Int;
|
||||
|
||||
var gemColor:String;
|
||||
|
||||
public var radarColor:Int;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue