mirror of
https://github.com/RandomityGuy/MBHaxe.git
synced 2026-04-22 10:41:38 +00:00
pathedinterior fix parsing
This commit is contained in:
parent
8d47fc0163
commit
8702305e79
12 changed files with 436 additions and 200 deletions
|
|
@ -1,5 +1,6 @@
|
|||
package src;
|
||||
|
||||
import h3d.shader.pbr.PropsValues;
|
||||
import shaders.Billboard;
|
||||
import shaders.DtsTexture;
|
||||
import h3d.mat.Pass;
|
||||
|
|
@ -100,6 +101,12 @@ class InstanceManager {
|
|||
minfo.transparencymeshbatch = new MeshBatch(cast(cast(obj, Mesh).primitive), cast(cast(obj, Mesh)).material.clone(), scene);
|
||||
minfo.transparencymeshbatch.material.mainPass.removeShader(minfo.meshbatch.material.textureShader);
|
||||
minfo.transparencymeshbatch.material.mainPass.addShader(dtsshader);
|
||||
|
||||
var pbrshader = mat.mainPass.getShader(PropsValues);
|
||||
if (pbrshader != null) {
|
||||
minfo.meshbatch.material.mainPass.addShader(pbrshader);
|
||||
minfo.transparencymeshbatch.material.mainPass.addShader(pbrshader);
|
||||
}
|
||||
}
|
||||
minfos.push(minfo);
|
||||
}
|
||||
|
|
|
|||
178
src/Main.hx
178
src/Main.hx
|
|
@ -1,5 +1,6 @@
|
|||
package;
|
||||
|
||||
import src.Mission;
|
||||
import mis.MisParser;
|
||||
import sys.io.File;
|
||||
import shapes.EndPad;
|
||||
|
|
@ -47,188 +48,21 @@ class Main extends hxd.App {
|
|||
override function init() {
|
||||
super.init();
|
||||
|
||||
dtsObj = new SuperSpeed();
|
||||
dtsObj.x = -3;
|
||||
|
||||
world = new MarbleWorld(s3d, s2d);
|
||||
|
||||
var db = new InteriorObject();
|
||||
db.interiorFile = "data/interiors/beginner/beginner_finish.dif";
|
||||
world.addInterior(db);
|
||||
var tform = db.getTransform();
|
||||
tform.setPosition(new Vector(0, 0, 0));
|
||||
db.setTransform(tform);
|
||||
|
||||
var ltr = File.getContent("data/missions/beginner/finale.mis");
|
||||
var mfp = new MisParser(ltr);
|
||||
var mis = mfp.parse();
|
||||
|
||||
// var pi = new PathedInterior();
|
||||
// DifBuilder.loadDif("data/interiors/addon/smallplatform.dif", loader, pi);
|
||||
// var pim = pi.getTransform();
|
||||
// pim.setPosition(new Vector(5, 0, 0));
|
||||
// pi.setTransform(pim);
|
||||
var mission = new Mission();
|
||||
mission.root = mis.root;
|
||||
|
||||
// var cube = new Polygon([new h3d.col.Point(0, 0, 0), new h3d.col.Point(0, 0, 1), new h3d.col.Point(0, 1, 0)]);
|
||||
// cube.addNormals();
|
||||
// cube.addUVs();
|
||||
// var tex = ResourceLoader.loader.load("data/interiors/arrow_cool1.jpg").toTexture();
|
||||
// var mat = Material.create(tex);
|
||||
// var mesh = new Mesh(cube, mat);
|
||||
// var go = new GameObject();
|
||||
// go.identifier = "lol";
|
||||
// go.addChild(mesh);
|
||||
// world.instanceManager.addObject(go);
|
||||
|
||||
// var m1 = new PathedInteriorMarker();
|
||||
// m1.msToNext = 5;
|
||||
// m1.position = new Vector(0, 0, 0);
|
||||
// m1.smoothingType = "";
|
||||
// m1.rotation = new Quat();
|
||||
|
||||
// var m2 = new PathedInteriorMarker();
|
||||
// m2.msToNext = 3;
|
||||
// m2.position = new Vector(0, 0, 5);
|
||||
// m2.smoothingType = "";
|
||||
// m2.rotation = new Quat();
|
||||
|
||||
// var m3 = new PathedInteriorMarker();
|
||||
// m3.msToNext = 5;
|
||||
// m3.position = new Vector(0, 0, 0);
|
||||
// m3.smoothingType = "";
|
||||
// m3.rotation = new Quat();
|
||||
|
||||
// pi.markerData = [m1, m2, m3];
|
||||
|
||||
// world.addPathedInterior(pi);
|
||||
|
||||
world.addDtsObject(dtsObj);
|
||||
|
||||
var sj = new SuperJump();
|
||||
sj.x = 3;
|
||||
world.addDtsObject(sj);
|
||||
|
||||
var sj2 = new SuperJump();
|
||||
sj2.x = 3;
|
||||
sj2.z = 2;
|
||||
world.addDtsObject(sj2);
|
||||
|
||||
var sb = new SuperBounce();
|
||||
sb.y = 3;
|
||||
world.addDtsObject(sb);
|
||||
|
||||
var sh = new ShockAbsorber();
|
||||
sh.y = -3;
|
||||
world.addDtsObject(sh);
|
||||
|
||||
var he = new Helicopter();
|
||||
world.addDtsObject(he);
|
||||
sj.setTransform(sj.getTransform());
|
||||
|
||||
var ag = new AntiGravity();
|
||||
ag.y = 6;
|
||||
world.addDtsObject(ag);
|
||||
|
||||
var os = new Oilslick();
|
||||
os.x = 5;
|
||||
os.z = 0.1;
|
||||
world.addDtsObject(os);
|
||||
|
||||
var tdoor = new Trapdoor();
|
||||
tdoor.x = -5;
|
||||
tdoor.z = 1;
|
||||
world.addDtsObject(tdoor);
|
||||
|
||||
var rb = new RoundBumper();
|
||||
rb.x = -5;
|
||||
rb.y = 2;
|
||||
world.addDtsObject(rb);
|
||||
|
||||
var tb = new TriangleBumper();
|
||||
tb.x = -5;
|
||||
tb.y = 4;
|
||||
world.addDtsObject(tb);
|
||||
|
||||
var spad = new StartPad();
|
||||
spad.x = 5;
|
||||
spad.y = 3;
|
||||
world.addDtsObject(spad);
|
||||
|
||||
var lm = new LandMine();
|
||||
lm.x = 7;
|
||||
world.addDtsObject(lm);
|
||||
|
||||
var epad = new EndPad();
|
||||
epad.x = 5;
|
||||
epad.x = -3;
|
||||
world.addDtsObject(epad);
|
||||
|
||||
// var le:ParticleEmitterOptions = {
|
||||
|
||||
// ejectionPeriod: 0.01,
|
||||
// ambientVelocity: new Vector(0, 0, 0),
|
||||
// ejectionVelocity: 0.5,
|
||||
// velocityVariance: 0.25,
|
||||
// emitterLifetime: 1e8,
|
||||
// inheritedVelFactor: 0.2,
|
||||
// particleOptions: {
|
||||
// texture: 'particles/smoke.png',
|
||||
// blending: Add,
|
||||
// spinSpeed: 40,
|
||||
// spinRandomMin: -90,
|
||||
// spinRandomMax: 90,
|
||||
// lifetime: 1,
|
||||
// lifetimeVariance: 0.15,
|
||||
// dragCoefficient: 0.8,
|
||||
// acceleration: 0,
|
||||
// colors: [new Vector(0.56, 0.36, 0.26, 1), new Vector(0.56, 0.36, 0.26, 0)],
|
||||
// sizes: [0.5, 1],
|
||||
// times: [0, 1]
|
||||
// }
|
||||
// };
|
||||
|
||||
// var p1 = new ParticleData();
|
||||
// p1.identifier = "testparticle";
|
||||
// p1.texture = ResourceLoader.getTexture("data/particles/smoke.png");
|
||||
|
||||
// // var emitter = new ParticleEmitter(le, p1, world.particleManager); // var p = new Particle();
|
||||
// world.particleManager.createEmitter(le, p1, new Vector());
|
||||
|
||||
// p.position = new Vector();
|
||||
// p.color = new Vector(255, 255, 255);
|
||||
// p.rotation = Math.PI;
|
||||
// p.scale = 5;
|
||||
|
||||
// world.particleManager.addParticle(p1, p);
|
||||
|
||||
// for (i in 0...10) {
|
||||
|
||||
// for (j in 0...10) {
|
||||
// var trapdoor = new Tornado();
|
||||
// trapdoor.x = i * 2;
|
||||
// trapdoor.y = j * 2;
|
||||
// world.addDtsObject(trapdoor);
|
||||
// }
|
||||
// }
|
||||
|
||||
// for (surf in db.collider.surfaces) {
|
||||
// var surfmin = new CustomObject(cube, mat, s3d);
|
||||
// var bound = surf.boundingBox;
|
||||
// surfmin.setPosition(bound.xMin, bound.yMin, bound.zMin);
|
||||
|
||||
// var surfmax = new CustomObject(cube, mat, s3d);
|
||||
// surfmax.setPosition(bound.xMax, bound.yMax, bound.zMax);
|
||||
// }
|
||||
|
||||
// var mat = Material.create();
|
||||
// var so = new CustomObject(cube, mat);
|
||||
// so.setPosition(0, 0, 0);
|
||||
// s3d.addChild(so);
|
||||
world = new MarbleWorld(s3d, s2d, mission);
|
||||
|
||||
var dirlight = new DirLight(new Vector(0.5, 0.5, -0.5), s3d);
|
||||
dirlight.enableSpecular = true;
|
||||
s3d.lightSystem.ambientLight.set(0.3, 0.3, 0.3);
|
||||
|
||||
world.init();
|
||||
|
||||
// s3d.camera.
|
||||
|
||||
var marble = new Marble();
|
||||
|
|
|
|||
|
|
@ -599,7 +599,8 @@ class Marble extends GameObject {
|
|||
var tform = obj.transform.clone();
|
||||
var velDir = obj.velocity.normalized();
|
||||
// tform.setPosition(tform.getPosition().add(velDir.multiply(_radius)));
|
||||
tform.setPosition(tform.getPosition().add(obj.velocity.multiply(dt)).sub(velDir.multiply(_radius)));
|
||||
// tform.setPosition(tform.getPosition().add(obj.velocity.multiply(dt)).sub(velDir.multiply(_radius)));
|
||||
tform.setPosition(tform.getPosition().add(obj.velocity.multiply(dt)));
|
||||
|
||||
var contacts = [];
|
||||
|
||||
|
|
@ -693,20 +694,19 @@ class Marble extends GameObject {
|
|||
var intersectT = this.getIntersectionTime(timeStep, velocity);
|
||||
|
||||
if (intersectT < timeStep) {
|
||||
intersectT *= 0.8; // We uh tick the shit to not actually at the contact time cause bruh
|
||||
// intersectT *= 0.8; // We uh tick the shit to not actually at the contact time cause bruh
|
||||
// intersectT /= 2;
|
||||
var diff = timeStep - intersectT;
|
||||
this.velocity = this.velocity.sub(A.multiply(diff));
|
||||
this.omega = this.omega.sub(a.multiply(diff));
|
||||
timeStep = intersectT;
|
||||
trace("CCD");
|
||||
}
|
||||
|
||||
piTime += timeStep;
|
||||
if (this.controllable) {
|
||||
for (interior in pathedInteriors) {
|
||||
// interior.popTickState();
|
||||
// interior.setStopped(stoppedPaths);
|
||||
interior.setStopped(stoppedPaths);
|
||||
var piDT = timeState.clone();
|
||||
piDT.currentAttemptTime = piTime;
|
||||
piDT.dt = timeStep;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,33 @@
|
|||
package src;
|
||||
|
||||
import triggers.HelpTrigger;
|
||||
import triggers.InBoundsTrigger;
|
||||
import triggers.OutOfBoundsTrigger;
|
||||
import shapes.Trapdoor;
|
||||
import shapes.Oilslick;
|
||||
import shapes.Tornado;
|
||||
import shapes.TimeTravel;
|
||||
import shapes.SuperSpeed;
|
||||
import shapes.ShockAbsorber;
|
||||
import shapes.LandMine;
|
||||
import shapes.AntiGravity;
|
||||
import shapes.SmallDuctFan;
|
||||
import shapes.DuctFan;
|
||||
import shapes.Helicopter;
|
||||
import shapes.TriangleBumper;
|
||||
import shapes.RoundBumper;
|
||||
import shapes.SuperBounce;
|
||||
import shapes.SignCaution;
|
||||
import shapes.SuperJump;
|
||||
import shapes.Gem;
|
||||
import shapes.SignPlain;
|
||||
import shapes.SignFinish;
|
||||
import shapes.EndPad;
|
||||
import shapes.StartPad;
|
||||
import h3d.Matrix;
|
||||
import mis.MisParser;
|
||||
import src.DifBuilder;
|
||||
import mis.MissionElement;
|
||||
import src.GameObject;
|
||||
import triggers.Trigger;
|
||||
import src.Mission;
|
||||
|
|
@ -35,6 +63,7 @@ class MarbleWorld extends Scheduler {
|
|||
public var pathedInteriors:Array<PathedInterior> = [];
|
||||
public var marbles:Array<Marble> = [];
|
||||
public var dtsObjects:Array<DtsObject> = [];
|
||||
public var triggers:Array<Trigger> = [];
|
||||
|
||||
var shapeImmunity:Array<DtsObject> = [];
|
||||
var shapeOrTriggerInside:Array<GameObject> = [];
|
||||
|
|
@ -43,7 +72,10 @@ class MarbleWorld extends Scheduler {
|
|||
public var bonusTime:Float = 0;
|
||||
public var sky:Sky;
|
||||
|
||||
var endPadElement:MissionElementStaticShape;
|
||||
|
||||
public var scene:Scene;
|
||||
public var scene2d:h2d.Scene;
|
||||
public var mission:Mission;
|
||||
|
||||
public var marble:Marble;
|
||||
|
|
@ -52,6 +84,8 @@ class MarbleWorld extends Scheduler {
|
|||
public var outOfBounds:Bool = false;
|
||||
public var outOfBoundsTime:TimeState;
|
||||
public var finishTime:TimeState;
|
||||
public var totalGems:Int = 0;
|
||||
public var gemCount:Int = 0;
|
||||
|
||||
var helpTextTimeState:Float = -1e8;
|
||||
var alertTextTimeState:Float = -1e8;
|
||||
|
|
@ -62,9 +96,38 @@ class MarbleWorld extends Scheduler {
|
|||
/** The new target camera orientation quat */
|
||||
public var newOrientationQuat = new Quat();
|
||||
|
||||
public function new(scene:Scene, scene2d:h2d.Scene) {
|
||||
this.collisionWorld = new CollisionWorld();
|
||||
public function new(scene:Scene, scene2d:h2d.Scene, mission:Mission) {
|
||||
this.scene = scene;
|
||||
this.scene2d = scene2d;
|
||||
this.mission = mission;
|
||||
}
|
||||
|
||||
public function init() {
|
||||
function scanMission(simGroup:MissionElementSimGroup) {
|
||||
for (element in simGroup.elements) {
|
||||
if ([
|
||||
MissionElementType.InteriorInstance,
|
||||
MissionElementType.Item,
|
||||
MissionElementType.PathedInterior,
|
||||
MissionElementType.StaticShape,
|
||||
MissionElementType.TSStatic
|
||||
].contains(element._type)) {
|
||||
// this.loadingState.total++;
|
||||
|
||||
// Override the end pad element. We do this because only the last finish pad element will actually do anything.
|
||||
if (element._type == MissionElementType.StaticShape) {
|
||||
var so:MissionElementStaticShape = cast element;
|
||||
if (so.datablock.toLowerCase() == 'endpad')
|
||||
this.endPadElement = so;
|
||||
}
|
||||
} else if (element._type == MissionElementType.SimGroup) {
|
||||
scanMission(cast element);
|
||||
}
|
||||
}
|
||||
};
|
||||
scanMission(this.mission.root);
|
||||
|
||||
this.collisionWorld = new CollisionWorld();
|
||||
this.playGui = new PlayGui();
|
||||
this.instanceManager = new InstanceManager(scene);
|
||||
this.particleManager = new ParticleManager(cast this);
|
||||
|
|
@ -73,6 +136,9 @@ class MarbleWorld extends Scheduler {
|
|||
sky.init(cast this);
|
||||
playGui.init(scene2d);
|
||||
scene.addChild(sky);
|
||||
|
||||
this.addSimGroup(this.mission.root);
|
||||
this.playGui.formatGemCounter(this.gemCount, this.totalGems);
|
||||
}
|
||||
|
||||
public function start() {
|
||||
|
|
@ -102,6 +168,8 @@ class MarbleWorld extends Scheduler {
|
|||
this.deselectPowerUp();
|
||||
|
||||
this.clearSchedule();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function updateGameState() {
|
||||
|
|
@ -125,6 +193,261 @@ class MarbleWorld extends Scheduler {
|
|||
}
|
||||
}
|
||||
|
||||
public function addSimGroup(simGroup:MissionElementSimGroup) {
|
||||
if (simGroup.elements.filter((element) -> element._type == MissionElementType.PathedInterior).length != 0) {
|
||||
// Create the pathed interior
|
||||
var pathedInterior = src.PathedInterior.createFromSimGroup(simGroup, cast this);
|
||||
this.addPathedInterior(pathedInterior);
|
||||
if (pathedInterior == null)
|
||||
return;
|
||||
|
||||
// if (pathedInterior.hasCollision)
|
||||
// this.physics.addInterior(pathedInterior);
|
||||
for (trigger in pathedInterior.triggers)
|
||||
this.triggers.push(trigger);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (element in simGroup.elements) {
|
||||
switch (element._type) {
|
||||
case MissionElementType.SimGroup:
|
||||
this.addSimGroup(cast element);
|
||||
case MissionElementType.InteriorInstance:
|
||||
this.addInteriorFromMis(cast element);
|
||||
case MissionElementType.StaticShape:
|
||||
this.addStaticShape(cast element);
|
||||
case MissionElementType.Item:
|
||||
this.addItem(cast element);
|
||||
case MissionElementType.Trigger:
|
||||
this.addTrigger(cast element);
|
||||
case MissionElementType.TSStatic:
|
||||
this.addTSStatic(cast element);
|
||||
case MissionElementType.ParticleEmitterNode:
|
||||
this.addParticleEmitterNode(cast element);
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function addInteriorFromMis(element:MissionElementInteriorInstance) {
|
||||
var difPath = this.mission.getDifPath(element.interiorfile);
|
||||
if (difPath == "")
|
||||
return;
|
||||
|
||||
var interior = new InteriorObject();
|
||||
interior.interiorFile = difPath;
|
||||
// DifBuilder.loadDif(difPath, interior);
|
||||
// this.interiors.push(interior);
|
||||
this.addInterior(interior);
|
||||
|
||||
var interiorPosition = MisParser.parseVector3(element.position);
|
||||
interiorPosition.x = -interiorPosition.x;
|
||||
var interiorRotation = MisParser.parseRotation(element.rotation);
|
||||
interiorRotation.x = -interiorRotation.x;
|
||||
interiorRotation.w = -interiorRotation.w;
|
||||
var interiorScale = MisParser.parseVector3(element.scale);
|
||||
// var hasCollision = interiorScale.x != = 0 && interiorScale.y != = 0 && interiorScale.z != = 0; // Don't want to add buggy geometry
|
||||
|
||||
// Fix zero-volume interiors so they receive correct lighting
|
||||
if (interiorScale.x == 0)
|
||||
interiorScale.x = 0.0001;
|
||||
if (interiorScale.y == 0)
|
||||
interiorScale.y = 0.0001;
|
||||
if (interiorScale.z == 0)
|
||||
interiorScale.z = 0.0001;
|
||||
|
||||
var mat = new Matrix();
|
||||
interiorRotation.toMatrix(mat);
|
||||
mat.scale(interiorScale.x, interiorScale.y, interiorScale.z);
|
||||
mat.setPosition(interiorPosition);
|
||||
|
||||
interior.setTransform(mat);
|
||||
|
||||
// interior.setTransform(interiorPosition, interiorRotation, interiorScale);
|
||||
|
||||
// this.scene.add(interior.group);
|
||||
// if (hasCollision)
|
||||
// this.physics.addInterior(interior);
|
||||
}
|
||||
|
||||
public function addStaticShape(element:MissionElementStaticShape) {
|
||||
var shape:DtsObject = null;
|
||||
|
||||
// Add the correct shape based on type
|
||||
var dataBlockLowerCase = element.datablock.toLowerCase();
|
||||
if (dataBlockLowerCase == "") {} // Make sure we don't do anything if there's no data block
|
||||
else if (dataBlockLowerCase == "startpad")
|
||||
shape = new StartPad();
|
||||
else if (dataBlockLowerCase == "endpad")
|
||||
shape = new EndPad();
|
||||
else if (dataBlockLowerCase == "signfinish")
|
||||
shape = new SignFinish();
|
||||
else if (StringTools.startsWith(dataBlockLowerCase, "signplain"))
|
||||
shape = new SignPlain(element);
|
||||
else if (StringTools.startsWith(dataBlockLowerCase, "gemitem")) {
|
||||
shape = new Gem(cast element);
|
||||
this.totalGems++;
|
||||
} else if (dataBlockLowerCase == "superjumpitem")
|
||||
shape = new SuperJump();
|
||||
else if (StringTools.startsWith(dataBlockLowerCase, "signcaution"))
|
||||
shape = new SignCaution(element);
|
||||
else if (dataBlockLowerCase == "superbounceitem")
|
||||
shape = new SuperBounce();
|
||||
else if (dataBlockLowerCase == "roundbumper")
|
||||
shape = new RoundBumper();
|
||||
else if (dataBlockLowerCase == "trianglebumper")
|
||||
shape = new TriangleBumper();
|
||||
else if (dataBlockLowerCase == "helicopteritem")
|
||||
shape = new Helicopter();
|
||||
else if (dataBlockLowerCase == "ductfan")
|
||||
shape = new DuctFan();
|
||||
else if (dataBlockLowerCase == "smallductfan")
|
||||
shape = new SmallDuctFan();
|
||||
else if (dataBlockLowerCase == "antigravityitem")
|
||||
shape = new AntiGravity();
|
||||
else if (dataBlockLowerCase == "landmine")
|
||||
shape = new LandMine();
|
||||
else if (dataBlockLowerCase == "shockabsorberitem")
|
||||
shape = new ShockAbsorber();
|
||||
else if (dataBlockLowerCase == "superspeeditem")
|
||||
shape = new SuperSpeed();
|
||||
else if (dataBlockLowerCase == "timetravelitem")
|
||||
shape = new TimeTravel(cast element);
|
||||
else if (dataBlockLowerCase == "tornado")
|
||||
shape = new Tornado();
|
||||
else if (dataBlockLowerCase == "trapdoor")
|
||||
shape = new Trapdoor();
|
||||
else if (dataBlockLowerCase == "oilslick")
|
||||
shape = new Oilslick();
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
var shapePosition = MisParser.parseVector3(element.position);
|
||||
shapePosition.x = -shapePosition.x;
|
||||
var shapeRotation = MisParser.parseRotation(element.rotation);
|
||||
shapeRotation.x = -shapeRotation.x;
|
||||
shapeRotation.w = -shapeRotation.w;
|
||||
var shapeScale = MisParser.parseVector3(element.scale);
|
||||
|
||||
// Apparently we still do collide with zero-volume shapes
|
||||
if (shapeScale.x == 0)
|
||||
shapeScale.x = 0.0001;
|
||||
if (shapeScale.y == 0)
|
||||
shapeScale.y = 0.0001;
|
||||
if (shapeScale.z == 0)
|
||||
shapeScale.z = 0.0001;
|
||||
|
||||
var mat = shapeRotation.toMatrix();
|
||||
mat.scale(shapeScale.x, shapeScale.y, shapeScale.z);
|
||||
mat.setPosition(shapePosition);
|
||||
|
||||
this.addDtsObject(shape);
|
||||
|
||||
shape.setTransform(mat);
|
||||
|
||||
// else if (dataBlockLowerCase == "pushbutton")
|
||||
// shape = new PushButton();
|
||||
}
|
||||
|
||||
public function addItem(element:MissionElementItem) {
|
||||
var shape:DtsObject = null;
|
||||
|
||||
// Add the correct shape based on type
|
||||
var dataBlockLowerCase = element.datablock.toLowerCase();
|
||||
if (dataBlockLowerCase == "") {} // Make sure we don't do anything if there's no data block
|
||||
else if (dataBlockLowerCase == "startpad")
|
||||
shape = new StartPad();
|
||||
else if (dataBlockLowerCase == "endpad")
|
||||
shape = new EndPad();
|
||||
else if (dataBlockLowerCase == "signfinish")
|
||||
shape = new SignFinish();
|
||||
else if (StringTools.startsWith(dataBlockLowerCase, "gemitem")) {
|
||||
shape = new Gem(cast element);
|
||||
this.totalGems++;
|
||||
} else if (dataBlockLowerCase == "superjumpitem")
|
||||
shape = new SuperJump();
|
||||
else if (dataBlockLowerCase == "superbounceitem")
|
||||
shape = new SuperBounce();
|
||||
else if (dataBlockLowerCase == "roundbumper")
|
||||
shape = new RoundBumper();
|
||||
else if (dataBlockLowerCase == "trianglebumper")
|
||||
shape = new TriangleBumper();
|
||||
else if (dataBlockLowerCase == "helicopteritem")
|
||||
shape = new Helicopter();
|
||||
else if (dataBlockLowerCase == "ductfan")
|
||||
shape = new DuctFan();
|
||||
else if (dataBlockLowerCase == "smallductfan")
|
||||
shape = new SmallDuctFan();
|
||||
else if (dataBlockLowerCase == "antigravityitem")
|
||||
shape = new AntiGravity();
|
||||
else if (dataBlockLowerCase == "landmine")
|
||||
shape = new LandMine();
|
||||
else if (dataBlockLowerCase == "shockabsorberitem")
|
||||
shape = new ShockAbsorber();
|
||||
else if (dataBlockLowerCase == "superspeeditem")
|
||||
shape = new SuperSpeed();
|
||||
else if (dataBlockLowerCase == "timetravelitem")
|
||||
shape = new TimeTravel(cast element);
|
||||
else if (dataBlockLowerCase == "tornado")
|
||||
shape = new Tornado();
|
||||
else if (dataBlockLowerCase == "trapdoor")
|
||||
shape = new Trapdoor();
|
||||
else if (dataBlockLowerCase == "oilslick")
|
||||
shape = new Oilslick();
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
var shapePosition = MisParser.parseVector3(element.position);
|
||||
shapePosition.x = -shapePosition.x;
|
||||
var shapeRotation = MisParser.parseRotation(element.rotation);
|
||||
shapeRotation.x = -shapeRotation.x;
|
||||
shapeRotation.w = -shapeRotation.w;
|
||||
var shapeScale = MisParser.parseVector3(element.scale);
|
||||
|
||||
// Apparently we still do collide with zero-volume shapes
|
||||
if (shapeScale.x == 0)
|
||||
shapeScale.x = 0.0001;
|
||||
if (shapeScale.y == 0)
|
||||
shapeScale.y = 0.0001;
|
||||
if (shapeScale.z == 0)
|
||||
shapeScale.z = 0.0001;
|
||||
|
||||
var mat = shapeRotation.toMatrix();
|
||||
mat.scale(shapeScale.x, shapeScale.y, shapeScale.z);
|
||||
mat.setPosition(shapePosition);
|
||||
|
||||
this.addDtsObject(shape);
|
||||
|
||||
shape.setTransform(mat);
|
||||
}
|
||||
|
||||
public function addTrigger(element:MissionElementTrigger) {
|
||||
var trigger:Trigger = null;
|
||||
|
||||
return;
|
||||
|
||||
// Create a trigger based on type
|
||||
if (element.datablock == "OutOfBoundsTrigger") {
|
||||
trigger = new OutOfBoundsTrigger(element, cast this);
|
||||
} else if (element.datablock == "InBoundsTrigger") {
|
||||
trigger = new InBoundsTrigger(element, cast this);
|
||||
} else if (element.datablock == "HelpTrigger") {
|
||||
trigger = new HelpTrigger(element, cast this);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
this.triggers.push(trigger);
|
||||
this.collisionWorld.addEntity(trigger.collider);
|
||||
}
|
||||
|
||||
public function addTSStatic(element:MissionElementTSStatic) {}
|
||||
|
||||
public function addParticleEmitterNode(element:MissionElementParticleEmitterNode) {}
|
||||
|
||||
public function addInterior(obj:InteriorObject) {
|
||||
this.interiors.push(obj);
|
||||
obj.init(cast this);
|
||||
|
|
@ -235,6 +558,40 @@ class MarbleWorld extends Scheduler {
|
|||
// TODO FIX
|
||||
}
|
||||
|
||||
public function pickUpGem(gem:Gem) {
|
||||
this.gemCount++;
|
||||
var string:String;
|
||||
|
||||
// Show a notification (and play a sound) based on the gems remaining
|
||||
if (this.gemCount == this.totalGems) {
|
||||
string = "You have all the gems, head for the finish!";
|
||||
// if (!this.rewinding)
|
||||
// AudioManager.play('gotallgems.wav');
|
||||
|
||||
// Some levels with this package end immediately upon collection of all gems
|
||||
// if (this.mission.misFile.activatedPackages.includes('endWithTheGems')) {
|
||||
// let
|
||||
// completionOfImpact = this.physics.computeCompletionOfImpactWithBody(gem.bodies[0], 2); // Get the exact point of impact
|
||||
// this.touchFinish(completionOfImpact);
|
||||
// }
|
||||
} else {
|
||||
string = "You picked up a gem. ";
|
||||
|
||||
var remaining = this.totalGems - this.gemCount;
|
||||
if (remaining == 1) {
|
||||
string += "Only one gem to go!";
|
||||
} else {
|
||||
string += '${remaining} gems to go!';
|
||||
}
|
||||
|
||||
// if (!this.rewinding)
|
||||
// AudioManager.play('gotgem.wav');
|
||||
}
|
||||
|
||||
displayAlert(string);
|
||||
this.playGui.formatGemCounter(this.gemCount, this.totalGems);
|
||||
}
|
||||
|
||||
function callCollisionHandlers(marble:Marble) {
|
||||
var contacts = this.collisionWorld.radiusSearch(marble.getAbsPos().getPosition(), marble._radius);
|
||||
var newImmunity = [];
|
||||
|
|
|
|||
|
|
@ -1,11 +1,16 @@
|
|||
package src;
|
||||
|
||||
import mis.MissionElement.MissionElementSimGroup;
|
||||
import src.ResourceLoader;
|
||||
|
||||
class Mission {
|
||||
public var root:MissionElementSimGroup;
|
||||
|
||||
public function new() {}
|
||||
|
||||
public function getDifPath(rawElementPath:String) {
|
||||
rawElementPath = rawElementPath.toLowerCase();
|
||||
var path = rawElementPath;
|
||||
var path = StringTools.replace(rawElementPath.substring(rawElementPath.indexOf('data/')), "\"", "");
|
||||
if (StringTools.contains(path, 'interiors_mbg/'))
|
||||
path = StringTools.replace(path, 'interiors_mbg/', 'interiors/');
|
||||
return path;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ class PathedInterior extends InteriorObject {
|
|||
var path:MissionElementPath;
|
||||
var simGroup:MissionElementSimGroup;
|
||||
var element:MissionElementPathedInterior;
|
||||
var triggers:Array<MustChangeTrigger> = [];
|
||||
|
||||
public var triggers:Array<MustChangeTrigger> = [];
|
||||
|
||||
public var markerData:Array<PathedInteriorMarker> = [];
|
||||
|
||||
|
|
@ -64,6 +65,8 @@ class PathedInterior extends InteriorObject {
|
|||
|
||||
DifBuilder.loadDif(difFile, pathedInterior, cast MisParser.parseNumber(interiorElement.interiorindex)); // (difFile, path, level, );
|
||||
|
||||
pathedInterior.identifier = difFile + interiorElement.interiorindex;
|
||||
|
||||
pathedInterior.simGroup = simGroup;
|
||||
pathedInterior.element = interiorElement;
|
||||
level.interiors.push(pathedInterior);
|
||||
|
|
@ -80,7 +83,10 @@ class PathedInterior extends InteriorObject {
|
|||
|
||||
public override function init(level:MarbleWorld) {
|
||||
this.basePosition = MisParser.parseVector3(this.element.baseposition);
|
||||
this.basePosition.x = -this.basePosition.x;
|
||||
this.baseOrientation = MisParser.parseRotation(this.element.baserotation);
|
||||
this.baseOrientation.x = -this.baseOrientation.x;
|
||||
this.baseOrientation.w = -this.baseOrientation.w;
|
||||
this.baseScale = MisParser.parseVector3(this.element.basescale);
|
||||
// this.hasCollision = this.baseScale.x != 0
|
||||
// && this.baseScale.y != = 0 && this.baseScale.z != = 0; // Don't want to add buggy geometry
|
||||
|
|
@ -133,9 +139,7 @@ class PathedInterior extends InteriorObject {
|
|||
popTickState();
|
||||
}
|
||||
|
||||
var transform = this.getTransformAtTime(this.getInternalTime(currentTime));
|
||||
|
||||
this.updatePosition();
|
||||
var transform = this.getTransformAtTime(this.getInternalTime(timeState.currentAttemptTime));
|
||||
|
||||
var position = transform.getPosition();
|
||||
this.prevPosition = this.currentPosition;
|
||||
|
|
@ -145,9 +149,11 @@ class PathedInterior extends InteriorObject {
|
|||
pushTickState();
|
||||
}
|
||||
// if (!stopped)
|
||||
// this.currentTime = currentTime;
|
||||
// this.currentTime = timeState.currentAttemptTime;
|
||||
|
||||
velocity = position.sub(this.prevPosition).multiply(1 / timeState.dt);
|
||||
|
||||
this.updatePosition();
|
||||
}
|
||||
|
||||
public function setStopped(stopped:Bool = true) {
|
||||
|
|
@ -191,11 +197,11 @@ class PathedInterior extends InteriorObject {
|
|||
this.duration = total;
|
||||
}
|
||||
|
||||
public function setTargetTime(now:Float, target:Float) {
|
||||
var currentInternalTime = this.getInternalTime(now);
|
||||
public function setTargetTime(now:TimeState, target:Float) {
|
||||
var currentInternalTime = this.getInternalTime(now.currentAttemptTime);
|
||||
this.currentTime = currentInternalTime; // Start where the interior currently is
|
||||
this.targetTime = target;
|
||||
this.changeTime = now;
|
||||
this.changeTime = now.currentAttemptTime;
|
||||
}
|
||||
|
||||
public function getInternalTime(externalTime:Float) {
|
||||
|
|
@ -224,8 +230,8 @@ class PathedInterior extends InteriorObject {
|
|||
// Incase there are no markers at all
|
||||
var mat = new Matrix();
|
||||
this.baseOrientation.toMatrix(mat);
|
||||
mat.setPosition(this.basePosition);
|
||||
mat.scale(this.baseScale.x, this.baseScale.y, this.baseScale.z);
|
||||
mat.setPosition(this.basePosition);
|
||||
return mat;
|
||||
} else {
|
||||
m1 = this.markerData[0];
|
||||
|
|
@ -274,13 +280,14 @@ class PathedInterior extends InteriorObject {
|
|||
}
|
||||
// Offset by the position of the first marker
|
||||
var firstPosition = this.markerData[0].position;
|
||||
position.sub(firstPosition);
|
||||
position.add(basePosition); // Add the base position
|
||||
position = position.sub(firstPosition);
|
||||
position = position.add(basePosition); // Add the base position
|
||||
|
||||
var mat = new Matrix();
|
||||
this.baseOrientation.toMatrix(mat);
|
||||
mat.setPosition(position);
|
||||
|
||||
mat.scale(this.baseScale.x, this.baseScale.y, this.baseScale.z);
|
||||
mat.setPosition(position);
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -277,6 +277,19 @@ class PlayGui {
|
|||
}
|
||||
}
|
||||
|
||||
public function formatGemCounter(collected:Int, total:Int) {
|
||||
var totalTenths = Math.floor(total / 10);
|
||||
var totalOnes = total % 10;
|
||||
|
||||
var collectedTenths = Math.floor(collected / 10);
|
||||
var collectedOnes = collected % 10;
|
||||
|
||||
gemCountNumbers[0].currentFrame = collectedTenths;
|
||||
gemCountNumbers[1].currentFrame = collectedOnes;
|
||||
gemCountNumbers[2].currentFrame = totalTenths;
|
||||
gemCountNumbers[3].currentFrame = totalOnes;
|
||||
}
|
||||
|
||||
public function formatTimer(time:Float) {
|
||||
var et = time * 1000;
|
||||
var thousandth = et % 10;
|
||||
|
|
|
|||
|
|
@ -181,9 +181,9 @@ class MisParser {
|
|||
}
|
||||
|
||||
function hasNextElement() {
|
||||
if (!elementHeadRegEx.match(this.text.substring(this.index)))
|
||||
if (!elementHeadRegEx.matchSub(this.text, this.index))
|
||||
return false;
|
||||
if (Util.indexOfIgnoreStringLiterals(this.text.substring(this.index, this.index + elementHeadRegEx.matchedPos().pos), '}') != -1)
|
||||
if (Util.indexOfIgnoreStringLiterals(this.text.substring(this.index, elementHeadRegEx.matchedPos().pos), '}') != -1)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -197,6 +197,7 @@ class MisParser {
|
|||
continue;
|
||||
elements.push(element);
|
||||
}
|
||||
|
||||
var endingBraceIndex = Util.indexOfIgnoreStringLiterals(this.text, '};', this.index);
|
||||
if (endingBraceIndex == -1)
|
||||
endingBraceIndex = this.text.length;
|
||||
|
|
@ -346,7 +347,6 @@ class MisParser {
|
|||
obj._name = name;
|
||||
obj.markers = sg.elements.map(x -> cast x);
|
||||
obj.markers.sort((a, b) -> cast MisParser.parseNumber(a.seqnum) - MisParser.parseNumber(b.seqnum));
|
||||
copyFields(obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
|
@ -428,8 +428,8 @@ class MisParser {
|
|||
if (StringTools.startsWith(x, '$ ') && this.variables[x] != null) {
|
||||
// Replace the variable with its value
|
||||
x = this.resolveExpression(this.variables[x]);
|
||||
} else if (StringTools.startsWith(x, ' "') && StringTools.endsWith(x, '" ')) {
|
||||
x = Util.unescape(x.substring(1, x.length - 2)); // It' s a string literal, so remove " "
|
||||
} else if (StringTools.startsWith(x, '"') && StringTools.endsWith(x, '"')) {
|
||||
x = Util.unescape(x.substring(1, x.length - 1)); // It' s a string literal, so remove " "
|
||||
}
|
||||
return x;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package shapes;
|
||||
|
||||
import h3d.shader.pbr.PropsValues;
|
||||
import src.MarbleWorld;
|
||||
import mis.MissionElement.MissionElementItem;
|
||||
import src.TimeState;
|
||||
import src.DtsObject;
|
||||
|
|
@ -18,11 +20,19 @@ class Gem extends DtsObject {
|
|||
var GEM_COLORS = ["blue", "red", "yellow", "purple", "green", "turquoise", "orange", "black"];
|
||||
var color = element.datablock.substring("GemItem".length);
|
||||
if (color.length == 0)
|
||||
GEM_COLORS[Math.floor(Math.random() * GEM_COLORS.length)];
|
||||
color = GEM_COLORS[Math.floor(Math.random() * GEM_COLORS.length)];
|
||||
this.identifier = "Gem" + color;
|
||||
this.matNameOverride.set('base.gem', color + ".gem");
|
||||
}
|
||||
|
||||
public override function init(level:MarbleWorld) {
|
||||
super.init(level);
|
||||
|
||||
for (material in this.materials) {
|
||||
material.mainPass.addShader(new PropsValues(1, 0, 0, 1));
|
||||
}
|
||||
}
|
||||
|
||||
public override function setHide(hide:Bool) {
|
||||
if (hide) {
|
||||
this.pickedUp = true;
|
||||
|
|
@ -39,7 +49,7 @@ class Gem extends DtsObject {
|
|||
return;
|
||||
this.pickedUp = true;
|
||||
this.setOpacity(0); // Hide the gem
|
||||
// this.level.pickUpGem(this);
|
||||
this.level.pickUpGem(this);
|
||||
// this.level.replay.recordMarbleInside(this);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,5 +16,6 @@ class SignCaution extends DtsObject {
|
|||
case "Danger":
|
||||
this.matNameOverride.set("base.cautionsign", "danger.cautionsign");
|
||||
}
|
||||
this.identifier = "CautionSign" + type;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,9 +18,11 @@ class SignPlain extends DtsObject {
|
|||
case "Left":
|
||||
this.matNameOverride.set("base.plainsign", "left.plainsign");
|
||||
case "Up":
|
||||
this.matNameOverride.set("base.plainsign", "uo.plainsign");
|
||||
this.matNameOverride.set("base.plainsign", "up.plainsign");
|
||||
case "Down":
|
||||
this.matNameOverride.set("base.plainsign", "down.plainsign");
|
||||
}
|
||||
|
||||
this.identifier = "SignPlain" + direction;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,9 +41,9 @@ class Trigger extends GameObject {
|
|||
var mat = new Matrix();
|
||||
var quat = MisParser.parseRotation(element.rotation);
|
||||
quat.toMatrix(mat);
|
||||
mat.setPosition(MisParser.parseVector3(element.position));
|
||||
var scale = MisParser.parseVector3(element.scale);
|
||||
mat.scale(scale.x, scale.y, scale.z);
|
||||
mat.setPosition(MisParser.parseVector3(element.position));
|
||||
|
||||
var vertices = [p1, p2, p3, p4, p5, p6, p7, p8].map((vert) -> vert.transformed(mat));
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue