diff --git a/Aquaria/AnimationEditor.cpp b/Aquaria/AnimationEditor.cpp index ed800f6..105c094 100644 --- a/Aquaria/AnimationEditor.cpp +++ b/Aquaria/AnimationEditor.cpp @@ -1074,14 +1074,33 @@ void AnimationEditor::applyTranslation() { int xdiff = editingBone->position.x - bcur->x; int ydiff = editingBone->position.y - bcur->y; - // all bones mode - for (int i = 0; i < editSprite->getCurrentAnimation()->getNumKeyframes(); ++i) + if(!core->getCtrlState()) { - BoneKeyframe *b = editSprite->getCurrentAnimation()->getKeyframe(i)->getBoneKeyframe(editingBone->boneIdx); - if (b) + // all bones in one anim mode + for (int i = 0; i < editSprite->getCurrentAnimation()->getNumKeyframes(); ++i) { - b->x += xdiff; - b->y += ydiff; + BoneKeyframe *b = editSprite->getCurrentAnimation()->getKeyframe(i)->getBoneKeyframe(editingBone->boneIdx); + if (b) + { + b->x += xdiff; + b->y += ydiff; + } + } + } + else + { + // all bones in all anims mode + for (int a = 0; a < editSprite->animations.size(); ++a) + { + for (int i = 0; i < editSprite->animations[a].getNumKeyframes(); ++i) + { + BoneKeyframe *b = editSprite->animations[a].getKeyframe(i)->getBoneKeyframe(editingBone->boneIdx); + if (b) + { + b->x += xdiff; + b->y += ydiff; + } + } } } } @@ -1187,12 +1206,30 @@ void AnimationEditor::rmbu() if (bcur) { int rotdiff = editingBone->rotation.z - bcur->rot; - for (int i = 0; i < editSprite->getCurrentAnimation()->getNumKeyframes(); ++i) + if (!core->getCtrlState()) { - BoneKeyframe *b = editSprite->getCurrentAnimation()->getKeyframe(i)->getBoneKeyframe(editingBone->boneIdx); - if (b) + for (int i = 0; i < editSprite->getCurrentAnimation()->getNumKeyframes(); ++i) { - b->rot += rotdiff; + BoneKeyframe *b = editSprite->getCurrentAnimation()->getKeyframe(i)->getBoneKeyframe(editingBone->boneIdx); + if (b) + { + b->rot += rotdiff; + } + } + } + else + { + // all bones in all anims mode + for (int a = 0; a < editSprite->animations.size(); ++a) + { + for (int i = 0; i < editSprite->animations[a].getNumKeyframes(); ++i) + { + BoneKeyframe *b = editSprite->animations[a].getKeyframe(i)->getBoneKeyframe(editingBone->boneIdx); + if (b) + { + b->rot += rotdiff; + } + } } } } diff --git a/Aquaria/AquariaMenuItem.cpp b/Aquaria/AquariaMenuItem.cpp index 71d8689..c288058 100644 --- a/Aquaria/AquariaMenuItem.cpp +++ b/Aquaria/AquariaMenuItem.cpp @@ -569,8 +569,7 @@ void AquariaKeyConfig::onUpdate(float dt) if (!ai) { - errorLog("Could not find actionInput: " + actionInputName); - exit(-1); + exit_error("Could not find actionInput: " + actionInputName); } switch(inputSetType) { @@ -589,14 +588,6 @@ void AquariaKeyConfig::onUpdate(float dt) } } - /* - if (k == 0) - { - errorLog("AquariaKeyConfig::onUpdate"); - exit(-1); - } - */ - int *value = 0; if (inputSetType == INPUTSET_OTHER) diff --git a/Aquaria/Avatar.cpp b/Aquaria/Avatar.cpp index a4c030f..f5c8885 100644 --- a/Aquaria/Avatar.cpp +++ b/Aquaria/Avatar.cpp @@ -120,6 +120,12 @@ const float NOTE_ACCEPT_ANGLE_OFFSET = 15; const int COLLIDE_RADIUS_NORMAL = 10; const int COLLIDE_RADIUS_FISH = 8; +const int COLLIDE_RANGE_NORMAL = 2; +const int COLLIDE_RANGE_FISH = 1; + +const float COLLIDE_MOD_NORMAL = 1.0f; +const float COLLIDE_MOD_FISH = 0.1f; + const int requiredDualFormCharge = 3; bool usingDigital = false; @@ -744,7 +750,7 @@ void Avatar::toggleMovement(bool on) bool Avatar::isLockable() { - return (bursting || !_isUnderWater) && (boneLockDelay == 0) && (dsq->continuity.form != FORM_FISH); + return (bursting || !_isUnderWater) && (boneLockDelay == 0) && canLockToWall(); } bool Avatar::isSinging() @@ -752,11 +758,6 @@ bool Avatar::isSinging() return singing; } -void Avatar::shift() -{ - dsq->continuity.shiftWorlds(); -} - void Avatar::applyWorldEffects(WorldType type) { static bool oldfh=false; @@ -1595,6 +1596,8 @@ void Avatar::changeForm(FormType form, bool effects, bool onInit, FormType lastF //rotationOffset.interpolateTo(Vector(0,0,0), 0.5); collideRadius = COLLIDE_RADIUS_NORMAL; + setCanLockToWall(true); + setCollisionAvoidanceData(COLLIDE_RANGE_NORMAL, COLLIDE_MOD_NORMAL); } break; case FORM_SUN: @@ -1606,9 +1609,13 @@ void Avatar::changeForm(FormType form, bool effects, bool onInit, FormType lastF position = bodyPosition; dsq->continuity.warpLiToAvatar(); spiritBeaconEmitter.start(); + setCanActivateStuff(true); + setCanLockToWall(true); + setCanBurst(true); + setDamageTarget(DT_WALLHURT, true); break; case FORM_BEAST: - //dsq->game->sceneColor3.interpolateTo(Vector(1, 1, 1), 0.5); + setCanSwimAgainstCurrents(false); break; case FORM_DUAL: if (dsq->continuity.hasLi()) @@ -1618,6 +1625,9 @@ void Avatar::changeForm(FormType form, bool effects, bool onInit, FormType lastF dsq->game->li->setState(STATE_IDLE); } break; + case FORM_NATURE: + setDamageTarget(DT_WALLHURT, true); + break; default: if (leftHandEmitter && rightHandEmitter) { @@ -1727,6 +1737,8 @@ void Avatar::changeForm(FormType form, bool effects, bool onInit, FormType lastF //refreshModel("NaijaFish", ""); collideRadius = COLLIDE_RADIUS_FISH; + setCanLockToWall(false); + setCollisionAvoidanceData(COLLIDE_RANGE_FISH, COLLIDE_MOD_FISH); } break; case FORM_SUN: @@ -1758,42 +1770,13 @@ void Avatar::changeForm(FormType form, bool effects, bool onInit, FormType lastF hair->setTexture("Naija/Cape-NatureForm"); hair->alphaMod = 1.0; } - /* - skeletalSprite.loadSkin("ChildTeira"); - refreshModel(); - */ - /* - if (dsq->game->sceneNatureForm == "forest") - { - debugLog("Forest Form"); - dsq->continuity.form = FORM_NATURE_FOREST; - } - else if (dsq->game->sceneNatureForm == "sun") - { - dsq->continuity.form = FORM_NATURE_SUN; - debugLog("Sun Form"); - } - else if (dsq->game->sceneNatureForm == "fire") - { - dsq->continuity.form = FORM_NATURE_FIRE; - debugLog("Fire Form"); - } - else if (dsq->game->sceneNatureForm == "dark") - { - dsq->continuity.form = FORM_NATURE_DARK; - debugLog("Dark Form"); - } - else if (dsq->game->sceneNatureForm == "rock" || dsq->game->sceneNatureForm.empty()) - { - dsq->continuity.form = FORM_NATURE_ROCK; - debugLog("Rock Form"); - } - */ + setDamageTarget(DT_WALLHURT, false); break; case FORM_BEAST: { refreshModel("Naija", "BeastForm"); + setCanSwimAgainstCurrents(true); } break; case FORM_SPIRIT: @@ -1801,6 +1784,10 @@ void Avatar::changeForm(FormType form, bool effects, bool onInit, FormType lastF bodyOffset = offset; fallOffWall(); dsq->continuity.shiftWorlds(); + setCanActivateStuff(false); + setCanLockToWall(false); + setCanBurst(false); + setDamageTarget(DT_WALLHURT, false); if (onInit) { @@ -2171,7 +2158,8 @@ void Avatar::loseTargets() void Avatar::updateTargetQuads(float dt) { - particleManager->setSuckPosition(1, dsq->getGameCursorPosition()); + const Vector cursorpos = dsq->getGameCursorPosition(); + particleManager->setSuckPosition(1, cursorpos); /* for (int i = 0; i < targetQuads.size(); i++) @@ -2202,7 +2190,8 @@ void Avatar::updateTargetQuads(float dt) targets[i].pos = e->getTargetPoint(targets[i].targetPt); if (i == 0) { - particleManager->setSuckPosition(1, targets[i].pos); + particleManager->setSuckPosition(1, targets[i].pos); // suckpos 1 is overridden elsewhere later + particleManager->setSuckPosition(2, targets[i].pos); } /* @@ -2215,7 +2204,7 @@ void Avatar::updateTargetQuads(float dt) } else { - targetQuads[i]->position = dsq->getGameCursorPosition(); + targetQuads[i]->position = cursorpos; //targetQuads[i]->alpha.interpolateTo(0, 0.1); } } @@ -2235,7 +2224,7 @@ void Avatar::updateTargetQuads(float dt) debugLog(os.str()); */ - targetQuads[i]->position = dsq->getGameCursorPosition(); + targetQuads[i]->position = cursorpos; if (dsq->continuity.form == FORM_ENERGY && isInputEnabled()) { if (dsq->inputMode == INPUT_JOYSTICK && targetQuads[i]->isRunning()) @@ -3495,8 +3484,8 @@ void Avatar::lockToWallCommon() void Avatar::lockToWall() { if (riding) return; - if (inCurrent && dsq->continuity.form != FORM_BEAST) return; - if (dsq->continuity.form == FORM_FISH || dsq->continuity.form == FORM_SPIRIT) return; + if (inCurrent && !canSwimAgainstCurrents()) return; + if (!canLockToWall()) return; if (state.lockedToWall) return; if (vel.x == 0 && vel.y == 0) return; if (dsq->game->isPaused()) return; @@ -3594,7 +3583,7 @@ void Avatar::lockToWall() } } - if (dsq->game->getGrid(t)==OT_HURT && dsq->continuity.form != FORM_NATURE) + if (dsq->game->getGrid(t)==OT_HURT && isDamageTarget(DT_WALLHURT)) { good = false; } @@ -4128,6 +4117,18 @@ Avatar::Avatar() : Entity(), ActionMapper() collideRadius = COLLIDE_RADIUS_FISH; else collideRadius = COLLIDE_RADIUS_NORMAL; + + // defaults for normal form + _canActivateStuff = true; + _canBurst = true; + _canLockToWall = true; + _canSwimAgainstCurrents = false; + _canCollideWithShots = true; + + _collisionAvoidMod = COLLIDE_MOD_NORMAL; + _collisionAvoidRange = COLLIDE_RANGE_NORMAL; + + _seeMapMode = SEE_MAP_DEFAULT; } void Avatar::revert() @@ -4324,7 +4325,7 @@ void Avatar::startBurstCommon() void Avatar::startBurst() { - if (!riding && dsq->continuity.form != FORM_SPIRIT && (joystickMove || getVectorToCursor().getSquaredLength2D() > sqr(BURST_DISTANCE)) + if (!riding && canBurst() && (joystickMove || getVectorToCursor().getSquaredLength2D() > sqr(BURST_DISTANCE)) && getState() != STATE_PUSH && (!skeletalSprite.getCurrentAnimation() || (skeletalSprite.getCurrentAnimation()->name != "spin")) && _isUnderWater && !isActing(ACTION_ROLL)) { @@ -4686,6 +4687,35 @@ void Avatar::action(int id, int state) } } +void Avatar::doBindSong() +{ + if (pullTarget) + { + pullTarget->stopPull(); + pullTarget = 0; + core->sound->playSfx("Denied"); + } + else + { + dsq->game->bindIngredients(); + setNearestPullTarget(); + if (!pullTarget) + { + core->sound->playSfx("Denied"); + } + else + { + core->sound->playSfx("Bind"); + } + } +} + +void Avatar::doShieldSong() +{ + core->sound->playSfx("Shield-On"); + activateAura(AURA_SHIELD); +} + void Avatar::render() { @@ -4858,10 +4888,6 @@ void Avatar::clampVelocity() } } - - - - if (!inCurrent || (inCurrent && withCurrent)) { if (dsq->continuity.form == FORM_FISH) @@ -4885,13 +4911,9 @@ void Avatar::clampVelocity() } - setMaxSpeed(currentMaxSpeed * useSpeedMult); - //float cheatLen = vel.getSquaredLength2D(); - vel.capLength2D(getMaxSpeed()); - /* - if (cheatLen > sqr(getMaxSpeed())) - vel.setLength2D(getMaxSpeed()); - */ + setMaxSpeed(currentMaxSpeed * useSpeedMult * dsq->continuity.speedMult2); + + vel.capLength2D(getMaxSpeed() * maxSpeedLerp.x); } void Avatar::activateAura(AuraType aura) @@ -5246,7 +5268,7 @@ void Avatar::updateWallJump(float dt) void Avatar::updateRoll(float dt) { - if (!inputEnabled || dsq->continuity.getWorldType() == WT_SPIRIT) + if (!inputEnabled || dsq->game->isWorldPaused()) { if (rolling) stopRoll(); @@ -5385,7 +5407,18 @@ void Avatar::setWasUnderWater() bool Avatar::canActivateStuff() { - return dsq->continuity.form != FORM_SPIRIT; + return _canActivateStuff; +} + +void Avatar::setCanActivateStuff(bool on) +{ + _canActivateStuff = on; +} + +void Avatar::setCollisionAvoidanceData(int range, float mod) +{ + _collisionAvoidRange = range; + _collisionAvoidMod = mod; } bool Avatar::canQuickSong() @@ -5705,38 +5738,6 @@ void Avatar::onUpdate(float dt) } - - // setup shader - if (core->afterEffectManager) - { - - /* - if (!_isUnderWater) - { - core->afterEffectManager->setActiveShader(AS_WASHOUT); - //core->afterEffectManager->setActiveShader(AS_NONE); - } - else - */ - if (dsq->user.video.shader != AS_NONE) - { - core->afterEffectManager->setActiveShader((ActiveShader)dsq->user.video.shader); - } - else - { - if (damageTimer.isActive() && dsq->isShakingCamera()) - { - if (dsq->user.video.blur) - core->afterEffectManager->setActiveShader(AS_BLUR); - } - else - { - core->afterEffectManager->setActiveShader(AS_NONE); - } - - } - } - Entity::onUpdate(dt); if (isEntityDead() && skeletalSprite.getCurrentAnimation()->name != "dead") @@ -6176,7 +6177,7 @@ void Avatar::onUpdate(float dt) //if (core->getNestedMains() == 1) { - if (getState() != STATE_TRANSFORM && dsq->continuity.getWorldType() == WT_NORMAL) + if (getState() != STATE_TRANSFORM && !dsq->game->isWorldPaused()) { formAbilityUpdate(dt); } @@ -6410,7 +6411,7 @@ void Avatar::onUpdate(float dt) } } - if (!state.lockedToWall && _isUnderWater && dsq->continuity.getWorldType() == WT_NORMAL && canMove) + if (!state.lockedToWall && _isUnderWater && !dsq->game->isWorldPaused() && canMove) { if (bursting) { @@ -6466,13 +6467,9 @@ void Avatar::onUpdate(float dt) if (getState() != STATE_PUSH && !state.lockedToWall && inputEnabled && _isUnderWater && canMove) { float a = 800*dt; - Vector lastVel = vel; Vector addVec; bool isMovingSlow = false; - static Vector lastMousePos; - Vector pos = lastMousePos - dsq->getGameCursorPosition(); - static bool lastDown; float len = 0; @@ -6480,8 +6477,6 @@ void Avatar::onUpdate(float dt) _isUnderWater && !riding && !boneLock.on && (movingOn || ((dsq->inputMode == INPUT_JOYSTICK || dsq->inputMode== INPUT_KEYBOARD) || (core->mouse.buttons.left || bursting)))) { - //addVec = getVectorToCursorFr - //(dsq->inputMode != INPUT_JOYSTICK && dsq->inputMode != INPUT_KEYBOARD) if (dsq->inputMode == INPUT_MOUSE || !this->singing) { addVec = getVectorToCursorFromScreenCentre();//getVectorToCursor(); @@ -6506,23 +6501,11 @@ void Avatar::onUpdate(float dt) addVec = Vector(0,0,0); } - - - /* - if (!core->mouse.buttons.left && bursting) - { - addVec = vel; - } - */ - if (!addVec.isLength2DIn(minMouse)) { //if (core->mouse.buttons.left) { len = addVec.getLength2D(); - // addVec is always overwritten below; I assume this is old code? --achurch - //if (len > 200) - // addVec.setLength2D(a *10); if (len > 100) addVec.setLength2D(a *2); else @@ -6556,31 +6539,11 @@ void Avatar::onUpdate(float dt) stopBurst(); } } - //vel = Vector(0,0,0); } addVec = Vector(0,0,0); } } - - //addVec |= a; - /* - if (pos.getSquaredLength2D() > 10000) - { - startBurst(); - } - */ } - else - { - } - lastDown = core->mouse.buttons.left; - - /* - std::ostringstream os; - os << "addVec(" << addVec.x << ", " << addVec.y << ")"; - debugLog(os.str()); - */ - lastMousePos = dsq->getGameCursorPosition(); if (!rolling && !state.backFlip && !flourish) { @@ -6613,20 +6576,6 @@ void Avatar::onUpdate(float dt) } } - - /* - // HACK: joystick code / slow - if (addVec.x == 0 && addVec.y == 0) - { - float jpos[2]; - glfwGetJoystickPos(GLFW_JOYSTICK_1, jpos, 2); - const float deadZone = 0.1; - if (fabsf(jpos[0]) > deadZone || fabsf(jpos[1]) > deadZone) - addVec = Vector(jpos[0]*a, -jpos[1]*a); - } - */ - - // will not get here if not underwater if (isLockable()) lockToWall(); @@ -6634,18 +6583,10 @@ void Avatar::onUpdate(float dt) { currentMaxSpeed=0; vel += addVec; - //addVec |= a; - //float cheatLen = vel.getSquaredLength2D(); + if (bursting) { Vector add = addVec; - /* - // HACK: this will let the player boost in one direction while turning to face another - if (!core->mouse.buttons.left) - { - add = vel; - } - */ add.setLength2D(BURST_ACCEL*dt); vel += add; @@ -6663,33 +6604,16 @@ void Avatar::onUpdate(float dt) { if (isActing(ACTION_SLOW) || isMovingSlow) { - /* - int spdRange = maxMouse - minMouse; - float p = (len - minMouse) / spdRange; - int spd = p * vars->maxSwimSpeed;// + minMouse - currentMaxSpeed = spd; - */ currentMaxSpeed = vars->maxSlowSwimSpeed; } - //else if (dsq->continuity.getWorldType() == WT_NORMAL) else currentMaxSpeed = vars->maxSwimSpeed; - /* - else - currentMaxSpeed = vars->maxDreamWorldSpeed; - */ } } - /* - if (dsq->continuity.form == FORM_SPIRIT) - currentMaxSpeed *= 0.5f; - */ - if (leaches > 0) { currentMaxSpeed -= leaches*60; - // vel |= vel.getLength2D()-1*leaches; } if (state.blind) @@ -6698,19 +6622,6 @@ void Avatar::onUpdate(float dt) if (currentMaxSpeed < 0) currentMaxSpeed = 1; - /* - if (inCurrent) - { - ropeState = 0; - currentMaxSpeed = 1200; - } - */ - - //clampVelocity(); - - - //float angle; - if (getState() == STATE_TRANSFORM) rotateToVec(addVec, 0.1, 90); else @@ -6738,13 +6649,6 @@ void Avatar::onUpdate(float dt) } else { - /* - if (bursting && !core->mouse.buttons.left) - { - } - else - rotateToVec(addVec, 0.1); - */ if (!state.nearWall && !flourish) rotateToVec(addVec, 0.1); } @@ -7054,13 +6958,9 @@ void Avatar::onUpdate(float dt) } - if (!state.lockedToWall && !bursting && _isUnderWater && swimming && !isFollowingPath()) + if (!state.lockedToWall && !bursting && _isUnderWater && swimming && !isFollowingPath() && _collisionAvoidRange > 0) { - //debugLog("collision avoidance"); - if (dsq->continuity.form == FORM_FISH) - doCollisionAvoidance(dt, 1, 0.1, 0, 800, OT_HURT); - else - doCollisionAvoidance(dt, 2, 1.0, 0, 800, OT_HURT); + doCollisionAvoidance(dt, _collisionAvoidRange, _collisionAvoidMod, 0, 800, OT_HURT); } if (!game->isShuttingDownGameState()) @@ -7077,7 +6977,11 @@ void Avatar::onUpdate(float dt) { /*collideCheck:*/ - if (vel.getLength2D() < sqr(2)) + // Beware: This code may cause clamping vel to zero if the framerate is very high. + // Starting with zero vel, low difftimes will cause an addVec small enough that this + // check will always trigger, and vel will never get larger than zero. + // Under water and swimming check should hopefully prevent this from happening. -- FG + if (_isUnderWater && !isSwimming() && vel.getLength2D() < sqr(2)) { vel = Vector(0,0,0); } @@ -7118,7 +7022,6 @@ void Avatar::onUpdate(float dt) else omov -= mov; - lastLastPosition = position; lastPosition = position; Vector newPosition = position + mov; //Vector testPosition = position + (vel *dt)*2; @@ -7127,11 +7030,11 @@ void Avatar::onUpdate(float dt) if (dsq->game->collideCircleWithGrid(position, collideRadius)) { if (dsq->game->lastCollideTileType == OT_HURT - && dsq->continuity.getWorldType() != WT_SPIRIT - && dsq->continuity.form != FORM_NATURE) + && isDamageTarget(DT_WALLHURT)) { DamageData d; d.damage = 1; + d.damageType = DT_WALLHURT; damage(d); vel2 = Vector(0,0,0); //doCollisionAvoidance(1, 3, 1); @@ -7294,7 +7197,8 @@ void Avatar::onUpdate(float dt) rightHandEmitter->position = boneRightHand->getWorldCollidePosition(Vector(0,16)); } - dsq->game->handleShotCollisions(this, (activeAura == AURA_SHIELD)); + if(canCollideWithShots()) + dsq->game->handleShotCollisions(this, (activeAura == AURA_SHIELD)); } @@ -7314,7 +7218,7 @@ void Avatar::checkNearWall() { t.x = oT.x + v.x*i; t.y = oT.y + v.y*i; - if (dsq->game->isObstructed(t) && dsq->game->getGrid(t) != OT_HURT) + if (dsq->game->isObstructed(t, ~OT_HURT)) { obs = true; break; diff --git a/Aquaria/Avatar.h b/Aquaria/Avatar.h index 0b8a196..0287a1d 100644 --- a/Aquaria/Avatar.h +++ b/Aquaria/Avatar.h @@ -66,6 +66,13 @@ enum AvatarAnimLayers ANIMLAYER_MAX }; +enum SeeMapMode +{ + SEE_MAP_NEVER = 0, + SEE_MAP_DEFAULT = 1, + SEE_MAP_ALWAYS = 2, +}; + class SongIconParticle : public Quad { public: @@ -160,7 +167,6 @@ public: Entity *entityToActivate; Path *pathToActivate; - void shift(); void applyWorldEffects(WorldType type); void toggleMovement(bool on); @@ -284,6 +290,7 @@ public: void endOfGameState(); bool canQuickSong(); bool canActivateStuff(); + void setCanActivateStuff(bool on); bool hasThingToActivate(); float biteTimer; @@ -317,8 +324,28 @@ public: bool canSetBoneLock(); void revert(); + void doBindSong(); + void doShieldSong(); + + bool canBurst() const { return _canBurst; } + void setCanBurst(bool b) { _canBurst = b; } + + bool canLockToWall() const { return _canLockToWall; } + void setCanLockToWall(bool b) { _canLockToWall = b; } + + bool canSwimAgainstCurrents() const { return _canSwimAgainstCurrents; } + void setCanSwimAgainstCurrents(bool b) { _canSwimAgainstCurrents = b; } + + bool canCollideWithShots() const { return _canCollideWithShots; } + void setCollideWithShots(bool b) { _canCollideWithShots = b; } + + void setCollisionAvoidanceData(int range, float mod); + + void setSeeMapMode(SeeMapMode mode) { _seeMapMode = mode; } + SeeMapMode getSeeMapMode() const { return _seeMapMode; } int leaches; + float shieldPoints; protected: void setSongIconPositions(); @@ -359,8 +386,6 @@ protected: Vector fallGravity; int lastOutOfWaterMaxSpeed; - int shieldPoints; - void onIdle(); void onHeal(int type); ParticleEffect biteLeftEmitter, biteRightEmitter, swimEmitter, auraHitEmitter; @@ -450,7 +475,15 @@ protected: void lockToWall(); void doShock(const std::string &shotName); - Vector lastLastPosition; + bool _canActivateStuff; + bool _canBurst; + bool _canLockToWall; + bool _canSwimAgainstCurrents; + bool _canCollideWithShots; + SeeMapMode _seeMapMode; + + int _collisionAvoidRange; + float _collisionAvoidMod; }; diff --git a/Aquaria/Beam.cpp b/Aquaria/Beam.cpp index 003fc7b..00dd262 100644 --- a/Aquaria/Beam.cpp +++ b/Aquaria/Beam.cpp @@ -142,7 +142,7 @@ void Beam::render() void Beam::onRender() { #ifdef BBGE_BUILD_OPENGL - glDisable(GL_CULL_FACE); + //glDisable(GL_CULL_FACE); Vector diff = endPos - position; Vector side = diff; //side.normalize2D(); diff --git a/Aquaria/Continuity.cpp b/Aquaria/Continuity.cpp index 063dd8a..8ad5fde 100644 --- a/Aquaria/Continuity.cpp +++ b/Aquaria/Continuity.cpp @@ -61,7 +61,7 @@ bool Continuity::isIngredientFull(IngredientData *data) { if (nocasecmp(ingredients[i]->name, data->name)==0) { - if (ingredients[i]->amount >= MAX_INGREDIENT_AMOUNT) + if (ingredients[i]->amount >= ingredients[i]->maxAmount) return true; else return false; @@ -70,22 +70,23 @@ bool Continuity::isIngredientFull(IngredientData *data) return false; } -void Continuity::pickupIngredient(IngredientData *d, int amount, bool effects) +void Continuity::pickupIngredient(IngredientData *d, int amount, bool effects, bool learn) { - learnRecipe(d->name, effects); + if(learn) + learnRecipe(d->name, effects); if (!getIngredientHeldByName(d->name)) { ingredients.push_back(d); } - if (d->amount < MAX_INGREDIENT_AMOUNT - amount) + if (d->amount < d->maxAmount - amount) { d->amount += amount; } else { - d->amount = MAX_INGREDIENT_AMOUNT; + d->amount = d->maxAmount; } } @@ -607,8 +608,10 @@ std::string Continuity::getAllIEString(IngredientData *data) return os.str(); } -void Continuity::applyIngredientEffects(IngredientData *data) +// returns true if eaten +bool Continuity::applyIngredientEffects(IngredientData *data) { + bool eaten = true; float y =0; for (int i = 0; i < data->effects.size(); i++) { @@ -841,28 +844,37 @@ void Continuity::applyIngredientEffects(IngredientData *data) // this item should only affect li if naija drops it and li eats it. } break; + case IET_SCRIPT: + { + // If this fails, it will still be eaten + if(dsq->game->cookingScript) + dsq->game->cookingScript->call("useIngredient", data->name.c_str(), &eaten); + } + break; default: { char str[256]; sprintf((char*)&str, "ingredient effect not defined, index[%d]", int(useType)); errorLog(str); + eaten = false; } break; } } + return eaten; } std::string Continuity::getIngredientAffectsString(IngredientData *data) { - - /* - std::string str; - for (int i = 0; i < data->effects.size(); i++) + if(data->type == IET_SCRIPT) { - str += splitCamelCase(getIngredientDescription(data->effects[i].type)) + "\n"; + if(dsq->game->cookingScript) + { + std::string ret = ""; + dsq->game->cookingScript->call("getIngredientString", data->name.c_str(), &ret); + return ret; + } } - return str; - */ return getAllIEString(data); } @@ -910,6 +922,43 @@ void Continuity::clearIngredientData() ingredientData.clear(); } +void Continuity::loadIngredientData() +{ + if(ingredients.size()) + { + debugLog("Can't reload ingredient data, inventory is not empty"); + return; // ... because otherwise there would be dangling pointers and it would crash. + } + + clearIngredientData(); + ingredientDescriptions.clear(); + ingredientDisplayNames.clear(); + recipes.clear(); + + loadIngredientDisplayNames("data/ingredientnames.txt"); + + std::string fname = localisePath("data/ingredientnames.txt"); + loadIngredientDisplayNames(fname); + + if(dsq->mod.isActive()) + { + fname = localisePath(dsq->mod.getPath() + "ingredientnames.txt", dsq->mod.getPath()); + loadIngredientDisplayNames(fname); + } + + if(dsq->mod.isActive()) + { + //load mod ingredients + loadIngredientData(dsq->mod.getPath() + "ingredients.txt"); + } + + //load ingredients for the main game + if(ingredientData.empty() && recipes.empty()) + { + loadIngredientData("data/ingredients.txt"); + } +} + void Continuity::loadIngredientData(const std::string &file) { std::string line, name, gfx, type, effects; @@ -920,6 +969,7 @@ void Continuity::loadIngredientData(const std::string &file) InStream in(file.c_str()); bool recipes = false; + bool extradata = false; while (std::getline(in, line)) { std::istringstream inLine(line); @@ -931,6 +981,11 @@ void Continuity::loadIngredientData(const std::string &file) recipes = true; break; } + else if(name == "==Extra==") + { + extradata = true; + break; + } inLine >> gfx >> type; std::getline(inLine, effects); @@ -1032,6 +1087,10 @@ void Continuity::loadIngredientData(const std::string &file) { fx.type = IET_LI; } + else if (bit.find("script") != std::string::npos) + { + fx.type = IET_SCRIPT; + } int c = 0; while (c < bit.size()) @@ -1052,6 +1111,31 @@ void Continuity::loadIngredientData(const std::string &file) ingredientData.push_back(data); } + if(extradata) + { + while (std::getline(in, line)) + { + SimpleIStringStream inLine(line.c_str(), SimpleIStringStream::REUSE); + int maxAmount = MAX_INGREDIENT_AMOUNT; + int rotKind = 1; + inLine >> name >> maxAmount >> rotKind; + if (name == "==Recipes==") + { + recipes = true; + break; + } + IngredientData *data = getIngredientDataByName(name); + if(!data) + { + errorLog("Specifying data for undefined ingredient: " + name); + continue; + } + + data->maxAmount = maxAmount; + data->rotKind = rotKind; + } + } + if (recipes) { bool quitNext = false; @@ -1347,16 +1431,6 @@ Song *Continuity::getSongByIndex(int idx) return &songBank[idx]; } -int Continuity::getSongBankSize() -{ - int c = 0; - for (SongMap::iterator i = songBank.begin(); i != songBank.end(); i++) - { - c++; - } - return c; -} - void Continuity::castSong(int num) { if (!dsq->continuity.hasSong((SongType)num)) return; @@ -1409,32 +1483,10 @@ void Continuity::castSong(int num) switch((SongType)num) { case SONG_SHIELDAURA: - core->sound->playSfx("Shield-On"); - dsq->game->avatar->activateAura(AURA_SHIELD); + dsq->game->avatar->doShieldSong(); break; case SONG_BIND: - //debugLog("sang pull"); - if (dsq->game->avatar->pullTarget) - { - dsq->game->avatar->pullTarget->stopPull(); - dsq->game->avatar->pullTarget = 0; - core->sound->playSfx("Denied"); - } - else - { - dsq->game->bindIngredients(); - dsq->game->avatar->setNearestPullTarget(); - if (!dsq->game->avatar->pullTarget) - { - core->sound->playSfx("Denied"); - } - else - { - core->sound->playSfx("Bind"); - } - } - //dsq->game->avatar->openPullTargetInterface(); - //pickingPullTarget = true; + dsq->game->avatar->doBindSong(); break; case SONG_ENERGYFORM: dsq->game->avatar->changeForm(FORM_ENERGY); @@ -1948,9 +2000,15 @@ void Continuity::shiftWorlds() { WorldType lastWorld = worldType; if (worldType == WT_NORMAL) + { worldType = WT_SPIRIT; + dsq->game->setWorldPaused(true); + } else if (worldType == WT_SPIRIT) + { worldType = WT_NORMAL; + dsq->game->setWorldPaused(false); + } FOR_ENTITIES(i) { Entity *e = *i; @@ -2336,15 +2394,34 @@ void Continuity::saveFile(int slot, Vector position, unsigned char *scrShotData, if (hasUserString) os << spacesToUnderscores((*i).userString) << " "; - - /* - std::ostringstream os2; - os2 << "Saving a Gem called [" << (*i).name << "] with userString [" << (*i).userString << "] pos (" << (*i).pos.x << ", " << (*i).pos.y << ")\n"; - os2 << os.str() << "\n"; - debugLog(os2.str()); - */ } gems.SetAttribute("c", os.str()); + + // This is the format used in the android version. Keeping this commented out for now, + // but it should be used instead of the code above in some time -- FG + /* + os.str(""); + bool hasMapName = false; + os << this->gems.size() << " "; + for (Gems::iterator i = this->gems.begin(); i != this->gems.end(); i++) + { + os << (*i).name << " "; + hasMapName = !(*i).mapName.empty(); + os << hasMapName << " "; + if(hasMapName) + os << (*i).mapName << " "; // warning: this will fail to load if the map name contains whitespace + + os << (*i).pos.x << " " << (*i).pos.y << " "; + os << (*i).canMove << " "; + + hasUserString = !(*i).userString.empty(); + os << hasUserString << " "; + if (hasUserString) + os << spacesToUnderscores((*i).userString) << " "; + } + gems.SetAttribute("d", os.str()); + */ + } doc.InsertEndChild(gems); @@ -2441,6 +2518,7 @@ void Continuity::saveFile(int slot, Vector position, unsigned char *scrShotData, startData.SetAttribute("scene", dsq->game->sceneName); startData.SetAttribute("exp", dsq->continuity.exp); startData.SetAttribute("h", dsq->continuity.maxHealth); + startData.SetAttribute("ch", dsq->continuity.health); startData.SetAttribute("naijaModel", dsq->continuity.naijaModel); startData.SetAttribute("costume", dsq->continuity.costume); startData.SetAttribute("form", dsq->continuity.form); @@ -2459,6 +2537,16 @@ void Continuity::saveFile(int slot, Vector position, unsigned char *scrShotData, } startData.SetAttribute("songs", os2.str()); + // new format as used by android version + std::ostringstream ingrNames; + for (int i = 0; i < ingredients.size(); i++) + { + IngredientData *data = ingredients[i]; + ingrNames << data->name << " " << data->amount << " "; + } + startData.SetAttribute("ingrNames", ingrNames.str()); + + // for compatibility with older versions std::ostringstream ingrOs; for (int i = 0; i < ingredients.size(); i++) { @@ -2492,6 +2580,74 @@ void Continuity::saveFile(int slot, Vector position, unsigned char *scrShotData, } startData.SetAttribute("intFlags", fos.str()); + // Additional data for the android version + +#define SINGLE_FLOAT_ATTR(name, cond, val) \ + do { if((cond) && (val)) { \ + std::ostringstream osf; \ + osf << (val); \ + startData.SetAttribute(name, osf.str()); \ + }} while(0) + + SINGLE_FLOAT_ATTR("blind", dsq->game->avatar->state.blind, dsq->game->avatar->state.blindTimer.getValue()); + SINGLE_FLOAT_ATTR("invincible", invincibleTimer.isActive(), invincibleTimer.getValue()); + SINGLE_FLOAT_ATTR("regen", regenTimer.isActive(), regenTimer.getValue()); + SINGLE_FLOAT_ATTR("trip", tripTimer.isActive(), tripTimer.getValue()); + SINGLE_FLOAT_ATTR("shieldPoints", true, dsq->game->avatar->shieldPoints); + SINGLE_FLOAT_ATTR("webTimer", webTimer.isActive(), webTimer.getValue()); // Extension; not present in the android version + +#undef SINGLE_FLOAT_ATTR + +#define TIMER_AND_VALUE_ATTR(name, timer, val) \ + do { if(((timer).isActive()) && (val)) { \ + std::ostringstream osf; \ + osf << (val) << " " << ((timer).getValue()); \ + startData.SetAttribute((name), osf.str()); \ + }} while(0) + + TIMER_AND_VALUE_ATTR("biteMult", biteMultTimer, biteMult); + TIMER_AND_VALUE_ATTR("speedMult", speedMultTimer, speedMult); + TIMER_AND_VALUE_ATTR("defenseMult", defenseMultTimer, defenseMult); + TIMER_AND_VALUE_ATTR("energyMult", energyTimer, energyMult); + TIMER_AND_VALUE_ATTR("petPower", petPowerTimer, petPower); + TIMER_AND_VALUE_ATTR("liPower", liPowerTimer, liPower); + TIMER_AND_VALUE_ATTR("light", lightTimer, light); + +#undef TIMER_AND_VALUE_ATTR + + if(poisonTimer.isActive()) + { + std::ostringstream osp; + osp << poison << " " << poisonTimer.getValue() << " " << poisonBitTimer.getValue(); + startData.SetAttribute("poison", osp.str()); + } + + if(dsq->game->avatar->activeAura != AURA_NONE) + { + std::ostringstream osa; + osa << dsq->game->avatar->activeAura << " " << dsq->game->avatar->auraTimer; + startData.SetAttribute("aura", osa.str()); + } + + // FIXME: Web is a bit weird. There are 2 webBitTimer variables in use, one in Continuity, one in Avatar. + // Because the avatar one ticks every 0.5 seconds, it will be hardly noticeable if that timer is off. + // So we just use the Continuty timers and hope for the best. -- FG + if(webTimer.isActive() && dsq->game->avatar->web) + { + Web *w = dsq->game->avatar->web; + const int nump = w->getNumPoints(); + std::ostringstream osw; + osw << webBitTimer.getValue() << " " << nump << " "; + for(int i = 0; i < nump; ++i) + { + Vector v = w->getPoint(i); + osw << v.x << " " << v.y << " "; + } + startData.SetAttribute("web", osw.str()); + } + + // end extra android data + doc.InsertEndChild(startData); @@ -2531,6 +2687,9 @@ std::string Continuity::getSaveFileName(int slot, const std::string &pfix) void Continuity::loadFileData(int slot, TiXmlDocument &doc) { std::string teh_file = dsq->continuity.getSaveFileName(slot, "aqs"); + if(!exists(teh_file)) + teh_file = dsq->continuity.getSaveFileName(slot, "bin"); + if (exists(teh_file)) { unsigned long size = 0; @@ -2568,7 +2727,7 @@ void Continuity::loadFile(int slot) if (startData->Attribute("mod")) { #ifdef AQUARIA_DEMO - exit(-1); + exit_error("The demo version does not support loading savegames from mods, sorry."); #else dsq->mod.load(startData->Attribute("mod")); #endif @@ -2714,6 +2873,7 @@ void Continuity::loadFile(int slot) this->gems.push_back(g); } } + // num [name mapX mapY canMove hasUserString (userString)] else if (gems->Attribute("c")) { std::string s = gems->Attribute("c"); @@ -2751,6 +2911,54 @@ void Continuity::loadFile(int slot) g.userString = underscoresToSpaces(g.userString); this->gems.push_back(g); + std::ostringstream os; + os << "Loading a Gem called [" << g.name << "] with userString [" << g.userString << "] pos (" << g.pos.x << ", " << g.pos.y << ")\n"; + debugLog(os.str()); + } + } + // num [name hasMapName (mapName) mapX mapY canMove hasUserString (userString)] + else if (gems->Attribute("d")) + { + std::string s = gems->Attribute("d"); + std::istringstream is(s); + + int num = 0; + is >> num; + + bool hasUserString = false; + bool hasMapName = false; + GemData g; + + std::ostringstream os; + os << "continuity num: [" << num << "]" << std::endl; + os << "data: [" << s << "]" << std::endl; + debugLog(os.str()); + + for (int i = 0; i < num; i++) + { + g.pos = Vector(0,0,0); + g.canMove = false; + g.userString = ""; + g.mapName = ""; + + hasUserString=false; + hasMapName = false; + + is >> g.name; + is >> hasMapName; + if(hasMapName) + is >> g.mapName; + + is >> g.pos.x >> g.pos.y; + is >> g.canMove; + is >> hasUserString; + + if (hasUserString) + is >> g.userString; + + g.userString = underscoresToSpaces(g.userString); + this->gems.push_back(g); + std::ostringstream os; os << "Loading a Gem called [" << g.name << "] with userString [" << g.userString << "] pos (" << g.pos.x << ", " << g.pos.y << ")\n"; debugLog(os.str()); @@ -2790,7 +2998,9 @@ void Continuity::loadFile(int slot) if (!tile) { - errorLog("tile dummy"); + std::ostringstream os; + os << "tile dummy: dropping data for worldmap tile index " << idx; + debugLog(os.str()); tile = &dummy; } @@ -2833,7 +3043,23 @@ void Continuity::loadFile(int slot) dsq->continuity.form = FormType(atoi(startData->Attribute("form"))); } - if (startData->Attribute("ingr")) + if (startData->Attribute("ingrNames")) + { + std::istringstream is(startData->Attribute("ingrNames")); + std::string name; + while (is >> name) + { + int amount=0; + is >> amount; + IngredientData *data = getIngredientDataByName(name); + if (data) + { + data->amount = 0; + pickupIngredient(data, amount, false); + } + } + } + else if (startData->Attribute("ingr")) // use this only if ingrNames does not exist. { std::istringstream is(startData->Attribute("ingr")); int idx; @@ -2898,7 +3124,7 @@ void Continuity::loadFile(int slot) if (startData->Attribute("h")) { - int read = atoi(startData->Attribute("h")); + float read = strtof(startData->Attribute("h"), NULL); maxHealth = read; health = read; std::ostringstream os; @@ -2911,6 +3137,21 @@ void Continuity::loadFile(int slot) dsq->game->avatar->health = maxHealth; } } + + if (startData->Attribute("ch")) + { + float h = strtof(startData->Attribute("ch"), NULL); + health = h; + std::ostringstream os; + os << "CurHealth read as: " << health; + debugLog(os.str()); + + if (dsq->game->avatar) + { + dsq->game->avatar->health = h; + } + } + if (startData->Attribute("seconds")) { std::istringstream is(startData->Attribute("seconds")); @@ -2921,9 +3162,124 @@ void Continuity::loadFile(int slot) dsq->continuity.costume = startData->Attribute("costume"); } - //dsq->game->positionToAvatar = Vector(500,400); dsq->game->sceneToLoad = startData->Attribute("scene"); - //dsq->game->transitionToScene(); + + // Additional data introduced in the android version + + if(startData->Attribute("blind")) + { + float timer = strtof(startData->Attribute("blind"), NULL); + if(dsq->game->avatar) + dsq->game->avatar->setBlind(timer); + } + + if(startData->Attribute("invincible")) + { + float timer = strtof(startData->Attribute("invincible"), NULL); + setInvincible(timer); + } + + if(startData->Attribute("regen")) + { + float timer = strtof(startData->Attribute("regen"), NULL); + setRegen(timer); + } + + if(startData->Attribute("trip")) + { + float timer = strtof(startData->Attribute("trip"), NULL); + setTrip(timer); + } + + if(startData->Attribute("aura")) + { + std::istringstream is(startData->Attribute("aura")); + int type = AURA_NONE; + float timer = 0.0f; + is >> type >> timer; + auraTimer = timer; + auraType = (AuraType)type; + if(dsq->game->avatar) + { + dsq->game->avatar->activateAura((AuraType)type); + dsq->game->avatar->auraTimer = timer; + } + } + + if(startData->Attribute("shieldPoints")) + { + float sp = strtof(startData->Attribute("shieldPoints"), NULL); + if(dsq->game->avatar) + dsq->game->avatar->shieldPoints = sp; + } + +#define LOAD_MULTI_SIMPLE(attr, mth) \ + do { if(startData->Attribute(attr)) \ + { \ + std::istringstream is(startData->Attribute(attr)); \ + float value = 0.0f, timer = 0.0f; \ + is >> value >> timer; \ + this->mth(value, timer); \ + }} while(0) + + LOAD_MULTI_SIMPLE("biteMult", setBiteMultiplier); + LOAD_MULTI_SIMPLE("speedMult", setSpeedMultiplier); + LOAD_MULTI_SIMPLE("defenseMult", setDefenseMultiplier); + LOAD_MULTI_SIMPLE("energyMult", setEnergy); + LOAD_MULTI_SIMPLE("petPower", setPetPower); + LOAD_MULTI_SIMPLE("liPower", setLiPower); + LOAD_MULTI_SIMPLE("light", setLight); + +#undef LOAD_MULTI_SIMPLE + + if(startData->Attribute("poison")) + { + std::istringstream is(startData->Attribute("poison")); + float p = 0.0f, pt = 0.0f, pbit = 0.0f; + is >> p >> pt >> pbit; + setPoison(p, pt); + poisonBitTimer.start(pbit); + } + + // FIXME: the total web time is seemingly not saved in the file. + // Not sure if the calculation of the remaining time is correct. + // Especially because there are two webBitTimer variables in use (in Continuity and Avatar), + // and both of them access the avatar web. It's thus likely that more points were added than intended. -- FG + if(startData->Attribute("web")) + { + std::istringstream is(startData->Attribute("web")); + float wbit = 0.0f; + int nump = 0; + is >> wbit >> nump; + // 2 web points are added in setWeb() by default, so we exclude them from the calculation + float remainTime = webTime - (0.5 * (nump - 2)); // Avatar::webBitTimer ticks every 0.5 secs + if(nump > 1 && remainTime > 0 && dsq->game->avatar) + { + if(!dsq->game->avatar->web) + dsq->game->avatar->createWeb(); + Web *w = dsq->game->avatar->web; + for(int i = 0; i < nump; ++i) + { + Vector v; + is >> v.x >> v.y; + if(i < w->getNumPoints()) + w->setPoint(i, v); + else + w->addPoint(v); + } + webBitTimer.start(wbit); + webTimer.start(remainTime); + } + } + + // This is AFAIK not in the android version, but let's add this for completeness + // and to avoid the mess described above. + if(startData->Attribute("webTimer")) + { + float timer = strtof(startData->Attribute("webTimer"), NULL); + webTimer.start(timer); + } + } } @@ -3079,6 +3435,7 @@ GemData *Continuity::pickupGem(std::string name, bool effects) { GemData g; g.name = name; + g.mapName = dsq->game->sceneName; int sz = gems.size(); //HACK: (hacky) using effects to determine the starting position of the gem @@ -3189,6 +3546,7 @@ void Continuity::reset() //worldMapTiles.clear(); speedMult = biteMult = fishPoison = defenseMult = 1; + speedMult2 = 1; poison = 0; energyMult = 0; light = petPower = 0; @@ -3218,40 +3576,11 @@ void Continuity::reset() worldMap.load(); - ingredients.clear(); naijaEats.clear(); - foodSortType = 0; + ingredients.clear(); - //load ingredients - - ingredientDisplayNames.clear(); - - loadIngredientDisplayNames("data/ingredientnames.txt"); - - std::string fname = localisePath("data/ingredientnames.txt"); - loadIngredientDisplayNames(fname); - - if(dsq->mod.isActive()) - { - fname = localisePath(dsq->mod.getPath() + "ingredientnames.txt", dsq->mod.getPath()); - loadIngredientDisplayNames(fname); - } - - ingredientDescriptions.clear(); - ingredientData.clear(); - recipes.clear(); - - if(dsq->mod.isActive()) - { - //load mod ingredients - loadIngredientData(dsq->mod.getPath() + "ingredients.txt"); - } - - //load ingredients for the main game - if(ingredientData.empty() && recipes.empty()) { - loadIngredientData("data/ingredients.txt"); - } + loadIngredientData(); // must be after clearing ingredients loadPetData(); diff --git a/Aquaria/CurrentRender.cpp b/Aquaria/CurrentRender.cpp index 7118480..fd40034 100644 --- a/Aquaria/CurrentRender.cpp +++ b/Aquaria/CurrentRender.cpp @@ -62,7 +62,7 @@ void CurrentRender::onRender() { #ifdef BBGE_BUILD_OPENGL // note: Leave cull_face disabled!? - glDisable(GL_CULL_FACE); + //glDisable(GL_CULL_FACE); //int qs = 0; for (Path *p = dsq->game->getFirstPathOfType(PATH_CURRENT); p; p = p->nextOfType) { @@ -308,7 +308,7 @@ void CurrentRender::onRender() //glEnd(); } - glEnable(GL_CULL_FACE); + //glEnable(GL_CULL_FACE); /* std::ostringstream os; diff --git a/Aquaria/DSQ.cpp b/Aquaria/DSQ.cpp index ae5b482..0b7ca9f 100644 --- a/Aquaria/DSQ.cpp +++ b/Aquaria/DSQ.cpp @@ -615,6 +615,7 @@ void DSQ::debugMenu() core->afterEffectManager->loadShaders(); } dsq->user.load(); + dsq->continuity.loadIngredientData(); } else if (c == '2') { @@ -922,12 +923,14 @@ This build is not yet final, and as such there are a couple things lacking. They // steam gets inited in here Core::init(); - // steam callbacks are inited here - dsq->continuity.init(); + dsq->continuity.stringBank.load(); vars = &v; v.load(); + // steam callbacks are inited here + dsq->continuity.init(); + // do copy stuff #ifdef BBGE_BUILD_UNIX std::string fn; @@ -997,8 +1000,7 @@ This build is not yet final, and as such there are a couple things lacking. They { std::ostringstream os; os << "Aspect ratio for resolution [" << user.video.resx << ", " << user.video.resy << "] not supported."; - errorLog(os.str()); - exit(0); + exit_error(os.str()); } setFilter(dsq_filter); @@ -1041,7 +1043,7 @@ This build is not yet final, and as such there are a couple things lacking. They if (!createWindow(user.video.resx, user.video.resy, user.video.bits, user.video.full, "Aquaria")) #endif { - msg("Failed to create window"); + exit_error("Failed to create window"); return; } @@ -1533,10 +1535,10 @@ This build is not yet final, and as such there are a couple things lacking. They renderObjectLayerOrder[LR_ENTITIES_MINUS3] = -1; renderObjectLayerOrder[LR_ENTITIES_MINUS2] = -1; - if (!Entity::blurShader.isLoaded()) + /*if (!Entity::blurShader.isLoaded()) { //Entity::blurShader.load("data/shaders/stan.vert", "data/shaders/hoblur.frag"); - } + }*/ setMousePosition(core->center); @@ -2155,7 +2157,6 @@ void DSQ::loadMods() // first load the packages, then enumerate XMLs forEachFile(mod.getBaseModPath(), ".aqmod", loadModPackagesCallback, 0); - forEachFile(mod.getBaseModPath(), ".zip", loadModPackagesCallback, 0); #endif forEachFile(mod.getBaseModPath(), ".xml", loadModsCallback, 0); @@ -2335,6 +2336,8 @@ void DSQ::playPositionalSfx(const std::string &name, const Vector &position, flo void DSQ::shutdown() { + mod.stop(); + Network::shutdown(); scriptInterface.shutdown(); @@ -4565,6 +4568,10 @@ void DSQ::onUpdate(float dt) os << " headRot: " << b->rotation.z; os << std::endl; os << "fh: " << dsq->game->avatar->isfh() << " fv: " << dsq->game->avatar->isfv() << std::endl; + os << "canActivate: " << dsq->game->avatar->canActivateStuff(); + os << " canBurst: " << dsq->game->avatar->canBurst(); + os << " canLTW: " << dsq->game->avatar->canLockToWall(); + os << " canSAC: " << dsq->game->avatar->canSwimAgainstCurrents() << std::endl; } // DO NOT CALL AVATAR-> beyond this point @@ -4577,6 +4584,7 @@ void DSQ::onUpdate(float dt) os << "altState: " << core->getKeyState(KEY_LALT) << " | " << core->getKeyState(KEY_RALT) << std::endl; os << "PMFree: " << particleManager->getFree() << " Active: " << particleManager->getNumActive() << std::endl; os << "cameraPos: (" << dsq->cameraPos.x << ", " << dsq->cameraPos.y << ")" << std::endl; + os << "worldType: " << continuity.getWorldType() << " worldPaused: " << game->isWorldPaused() << std::endl; os << "voiceTime: " << dsq->sound->getVoiceTime() << " bNat: " << dsq->game->bNatural; int ca, ma; dsq->sound->getStats(&ca, &ma); @@ -4591,7 +4599,7 @@ void DSQ::onUpdate(float dt) if (isDeveloperKeys() && fpsText && cmDebug && cmDebug->alpha == 1) { std::ostringstream os; - os << "FPS: " << core->fps << " | ROC: " << core->renderObjectCount; + os << "FPS: " << core->fps << " | ROC: " << core->renderObjectCount << " | RC: " << Core::dbg_numRenderCalls; os << " | p: " << core->processedRenderObjectCount << " | t: " << core->totalRenderObjectCount; os << " | s: " << dsq->continuity.seconds; os << " | evQ: " << core->eventQueue.getSize(); diff --git a/Aquaria/DSQ.h b/Aquaria/DSQ.h index 258617e..a1db87e 100644 --- a/Aquaria/DSQ.h +++ b/Aquaria/DSQ.h @@ -257,6 +257,7 @@ class Mod { public: Mod(); + ~Mod(); void clear(); void setActive(bool v); void start(); @@ -297,6 +298,7 @@ protected: std::string name; std::string path; + Precacher modcache; }; class AquariaScreenTransition : public ScreenTransition @@ -616,6 +618,7 @@ struct GemData GemData() { canMove=false; } std::string name; std::string userString; + std::string mapName; bool canMove; Vector pos; }; @@ -683,6 +686,7 @@ enum IngredientEffectType IET_POISON = 17, IET_BLIND = 18, IET_ALLSTATUS = 19, + IET_SCRIPT = 20, IET_MAX }; @@ -713,9 +717,11 @@ public: std::string displayName; const IngredientType type; int amount; + int maxAmount; int held; int marked; bool sorted; + bool rotKind; bool hasIET(IngredientEffectType iet); typedef std::vector IngredientEffects; @@ -945,7 +951,7 @@ public: std::string getSaveFileName(int slot, const std::string &pfix); - int maxHealth; + float maxHealth; float health; bool hudVisible; unsigned int exp; @@ -996,7 +1002,6 @@ public: FormUpgrades formUpgrades; void loadSongBank(); - int getSongBankSize(); void loadIntoSongBank(const std::string &file); int checkSong(const Song &song); int checkSongAssisted(const Song &song); @@ -1050,7 +1055,7 @@ public: std::string getSongNameBySlot(int slot); void toggleLiCombat(bool t); - void pickupIngredient(IngredientData *i, int amount, bool effects=true); + void pickupIngredient(IngredientData *i, int amount, bool effects=true, bool learn=true); int indexOfIngredientData(const IngredientData* data) const; IngredientData *getIngredientHeldByName(const std::string &name) const; // an ingredient that the player actually has; in the ingredients list IngredientData *getIngredientDataByName(const std::string &name); // an ingredient in the general data list; ingredientData @@ -1058,8 +1063,9 @@ public: IngredientData *getIngredientHeldByIndex(int idx) const; IngredientData *getIngredientDataByIndex(int idx); - void applyIngredientEffects(IngredientData *data); + bool applyIngredientEffects(IngredientData *data); + void loadIngredientData(); void loadIngredientData(const std::string &file); void loadIngredientDisplayNames(const std::string& file); bool hasIngredients() const { return !ingredients.empty(); } @@ -1098,6 +1104,8 @@ public: Timer energyTimer, poisonTimer, poisonBitTimer; Timer webTimer, webBitTimer, lightTimer, petPowerTimer; + float speedMult2; + void eatBeast(const EatData &eatData); void removeNaijaEat(int idx); void removeLastNaijaEat(); diff --git a/Aquaria/Entity.cpp b/Aquaria/Entity.cpp index 8e7f027..e394019 100644 --- a/Aquaria/Entity.cpp +++ b/Aquaria/Entity.cpp @@ -27,7 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "ScriptedEntity.h" #include "Shot.h" -Shader Entity::blurShader; +//Shader Entity::blurShader; void Entity::stopPull() { @@ -1080,7 +1080,7 @@ void Entity::onFHScale() copySkel.alpha.interpolateTo(0, 0.5); */ //skeletalSprite.alpha.interpolateTo(1,sct); - blurShaderAnim.interpolateTo(Vector(blurMin,0,0), sct); + //blurShaderAnim.interpolateTo(Vector(blurMin,0,0), sct); fhScale = 0; } @@ -1105,8 +1105,8 @@ void Entity::onFH() flipScale.interpolateTo(Vector(0.6, 1), sct); - blurShaderAnim = Vector(blurMin); - blurShaderAnim.interpolateTo(Vector(blurMax,0,0), sct/2); + //blurShaderAnim = Vector(blurMin); + //blurShaderAnim.interpolateTo(Vector(blurMax,0,0), sct/2); fhScale = 1; } @@ -1142,9 +1142,9 @@ void Entity::update(float dt) if (doUpdate && !dsq->game->isPaused()) { - if (getEntityType() == ET_ENEMY || getEntityType() == ET_NEUTRAL || getEntityType() == ET_PET) + if (!(getEntityType() == ET_AVATAR || getEntityType() == ET_INGREDIENT)) { - if (spiritFreeze && dsq->continuity.getWorldType() == WT_SPIRIT) + if (spiritFreeze && dsq->game->isWorldPaused()) { // possible bug here because of return return; @@ -1382,7 +1382,7 @@ bool Entity::updateCurrents(float dt) // why? { //Path *p = dsq->game->getNearestPath(position, PATH_CURRENT); - if (dsq->continuity.getWorldType() != WT_SPIRIT) + if (!dsq->game->isWorldPaused()) { for (Path *p = dsq->game->getFirstPathOfType(PATH_CURRENT); p; p = p->nextOfType) { @@ -1419,7 +1419,7 @@ bool Entity::updateCurrents(float dt) float useLen = len; if (useLen < 500) useLen = 500; - if (!(this->getEntityType() == ET_AVATAR && dsq->continuity.form == FORM_BEAST && dsq->game->avatar->bursting)) + if (!(this->getEntityType() == ET_AVATAR && dsq->game->avatar->canSwimAgainstCurrents() && dsq->game->avatar->bursting)) { doCollisionAvoidance(1, 4, 1, &vel2, useLen); } @@ -1439,7 +1439,7 @@ bool Entity::updateCurrents(float dt) } } } - if (this->getEntityType() == ET_AVATAR && dsq->continuity.form == FORM_BEAST) + if (this->getEntityType() == ET_AVATAR && dsq->game->avatar->canSwimAgainstCurrents()) { int cap = 100; if (!vel.isZero()) @@ -1681,7 +1681,7 @@ void Entity::onUpdate(float dt) break; } - blurShaderAnim.update(dt); + //blurShaderAnim.update(dt); } @@ -2832,23 +2832,18 @@ void Entity::render() // HACK: need to multiply base + etc skeletalSprite.setColorMult(this->color, this->alpha.x); - bool set=false; + /*bool set=false; if (beautyFlip && blurShader.isLoaded() && flipScale.isInterpolating() && dsq->user.video.blur) { - /* - std::ostringstream os; - os << "blurShaderAnim: " << blurShaderAnim.x; - debugLog(os.str()); - */ //swizzle blurShader.setValue(color.x, color.y, color.z, blurShaderAnim.x); blurShader.bind(); set = true; - } + }*/ Quad::render(); //if (beautyFlip && blurShader.isLoaded() && flipScale.isInterpolating()) - if (set) - blurShader.unbind(); + //if (set) + // blurShader.unbind(); renderBorder = false; skeletalSprite.clearColorMult(); color = bcolor; @@ -3133,3 +3128,14 @@ void Entity::exertHairForce(const Vector &force, float dt) } } +bool Entity::isEntityInside() +{ + FOR_ENTITIES(i) + { + Entity *e = *i; + if (e && e->life == 1 && e != this && e->ridingOnEntity != this && isCoordinateInside(e->position)) + return true; + + } + return false; +} diff --git a/Aquaria/Entity.h b/Aquaria/Entity.h index 336ccf3..70c7a51 100644 --- a/Aquaria/Entity.h +++ b/Aquaria/Entity.h @@ -123,6 +123,7 @@ enum DamageType DT_CRUSH = 1032, DT_SPIKES = 1033, DT_STEAM = 1034, + DT_WALLHURT = 1035, DT_REALMAX }; @@ -436,6 +437,7 @@ public: void setDieTimer(float v) { dieTimer = v; } float getHealthPerc(); void setDeathScene(bool v); + bool isDeathScene() const { return deathScene; } void generateCollisionMask(int ovrCollideRadius=0); DamageData lastDamage; bool checkSplash(const Vector &override=Vector(0,0,0)); @@ -450,7 +452,7 @@ public: //bool registerEntityDied; bool clampToSurface(int tcheck=0, Vector usePos=Vector(0,0), TileVector hitTile=TileVector(0,0)); bool checkSurface(int tcheck, int state, float statet); - static Shader blurShader; + //static Shader blurShader; std::string naijaReaction; Vector lookAtPoint; Vector getLookAtPoint(); @@ -488,6 +490,8 @@ public: void setHairHeadPosition(const Vector &pos); void exertHairForce(const Vector &force, float dt); + bool isEntityInside(); + protected: bool calledEntityDied; Path *waterBubble; @@ -514,7 +518,7 @@ protected: int lance; Bone *lanceBone; void updateLance(float dt); - InterpolatedVector blurShaderAnim; + //InterpolatedVector blurShaderAnim; int fhScale, fvScale; diff --git a/Aquaria/Game.cpp b/Aquaria/Game.cpp index 63748d7..1520c8d 100644 --- a/Aquaria/Game.cpp +++ b/Aquaria/Game.cpp @@ -394,7 +394,7 @@ void FoodSlot::refresh(bool effects) { std::ostringstream os; if (i->amount > 1) - os << i->amount << "/" << MAX_INGREDIENT_AMOUNT; + os << i->amount << "/" << i->maxAmount; label->setText(os.str()); setTexture("Ingredients/" + i->gfx); renderQuad = true; @@ -456,10 +456,13 @@ void FoodSlot::eatMe() if (!ingredient->effects.empty()) { - ingredient->amount--; - dsq->continuity.applyIngredientEffects(ingredient); - dsq->continuity.removeEmptyIngredients(); - dsq->game->refreshFoodSlots(true); + bool eaten = dsq->continuity.applyIngredientEffects(ingredient); + if(eaten) + { + ingredient->amount--; + dsq->continuity.removeEmptyIngredients(); + dsq->game->refreshFoodSlots(true); + } } else { @@ -533,7 +536,7 @@ void FoodSlot::onUpdate(float dt) Vector wp = getWorldPosition(); - if ((dsq->game->lips->getWorldPosition() - getWorldPosition()).isLength2DIn(32)) + if ((dsq->game->lips->getWorldPosition() - wp).isLength2DIn(32)) { dsq->menuSelectDelay = 0.5; @@ -548,7 +551,7 @@ void FoodSlot::onUpdate(float dt) bool droppedIn = false; for (int i = 0; i < foodHolders.size(); i++) { - bool in = (foodHolders[i]->getWorldPosition() - getWorldPosition()).isLength2DIn(32); + bool in = (foodHolders[i]->getWorldPosition() - wp).isLength2DIn(32); if (in) { droppedIn = true; @@ -587,11 +590,6 @@ void FoodSlot::onUpdate(float dt) label->alpha = 1; grabTime = 0; - if (dsq->inputMode == INPUT_JOYSTICK) - { - dsq->game->adjustFoodSlotCursor(); - } - return; } else @@ -1233,6 +1231,10 @@ Game::Game() : StateObject() loadEntityTypeList(); + lastCollideMaskIndex = -1; + worldPaused = false; + + cookingScript = 0; } @@ -2430,8 +2432,7 @@ void Game::loadEntityTypeList() std::string line; if(!in) { - core->messageBox(dsq->continuity.stringBank.get(2008), dsq->continuity.stringBank.get(2016)); - exit(1); + exit_error(dsq->continuity.stringBank.get(2008).c_str()); } while (std::getline(in, line)) { @@ -5211,7 +5212,7 @@ bool Game::loadScene(std::string scene) } if (i == allowedMaps.size()) { - exit(-1); + exit_error("Demo version refuses to load this map, sorry."); } #endif @@ -5717,7 +5718,7 @@ void Game::updateParticlePause() { core->particlesPaused = 2; } - else if (dsq->continuity.getWorldType() == WT_SPIRIT) + else if (this->isWorldPaused()) { core->particlesPaused = 1; } @@ -5834,41 +5835,6 @@ float Game::getHalfTimer(float mod) return halfTimer*mod; } -void Game::adjustFoodSlotCursor() -{ - // using visible slots now, don't need this atm - return; - /* - for (int i = 0; i < foodSlots.size(); i++) - { - if (foodSlots[i]->isCursorIn()) - { - if (!foodSlots[i]->getIngredient() || foodSlots[i]->getIngredient()->amount <= 0) - { - foodSlots[i]->setFocus(false); - i--; - while (i >= 0) - { - if (foodSlots[i]->getIngredient() && foodSlots[i]->getIngredient()->amount > 0) - { - //cursor->position = foodSlots[i]->getWorldPosition(); - foodSlots[i]->setFocus(true); - break; - } - i--; - } - if (i <= -1) - { - menu[5]->setFocus(true); - //cursor->position = menu[5]->getWorldPosition(); - } - } - break; - } - } - */ -} - void Game::action(int id, int state) { for (int i = 0; i < paths.size(); i++) @@ -5992,7 +5958,6 @@ void Game::action(int id, int state) if (foodSlots[i]->isCursorIn() && foodSlots[i]->getIngredient()) { foodSlots[i]->moveRight(); - adjustFoodSlotCursor(); break; } } @@ -6029,7 +5994,6 @@ void Game::action(int id, int state) if (ingrIndex >= 0) { foodSlots[ingrIndex]->discard(); - adjustFoodSlotCursor(); } } } @@ -6707,6 +6671,14 @@ void Game::applyState() musicToPlay = overrideMusic; } + if(cookingScript) + dsq->scriptInterface.closeScript(cookingScript); + + if (dsq->mod.isActive()) + cookingScript = dsq->scriptInterface.openScript(dsq->mod.getPath() + "scripts/cooking.lua", true); + else + cookingScript = dsq->scriptInterface.openScript("scripts/global/cooking.lua", true); + //INFO: this used to be here to start fading out the music // before the level had begun /* @@ -7242,7 +7214,22 @@ void Game::onCook() if (r) data = dsq->continuity.getIngredientDataByName(r->result); - else + else if(cookingScript) + { + const char *p1 = cookList[0]->name.c_str(); + const char *p2 = cookList[1]->name.c_str(); + const char *p3 = cookList.size() >= 3 ? cookList[2]->name.c_str() : ""; + std::string ingname; + if(cookingScript->call("cookFailure", p1, p2, p3, &ingname)) + { + if(ingname.length()) + data = dsq->continuity.getIngredientDataByName(ingname); + if(!data) + goto endcook; + } + } + + if(!data) { dsq->sound->playSfx("Denied"); data = dsq->continuity.getIngredientDataByName("SeaLoaf"); @@ -7422,6 +7409,8 @@ void Game::onCook() } refreshFoodSlots(true); +endcook: + AquariaGuiElement::canDirMoveGlobal = true; isCooking = false; @@ -8356,7 +8345,7 @@ void Game::registerSporeDrop(const Vector &pos, int t) bool Game::isEntityCollideWithShot(Entity *e, Shot *shot) { - if (!shot->isHitEnts()) + if (!shot->isHitEnts() || shot->firer == e) { return false; } @@ -8367,24 +8356,17 @@ bool Game::isEntityCollideWithShot(Entity *e, Shot *shot) } if (e->getEntityType() == ET_ENEMY) { - if (shot->firer != e) + if (shot->getDamageType() == DT_AVATAR_BITE) { - if (shot->getDamageType() == DT_AVATAR_BITE) + Avatar::BittenEntities::iterator i; + for (i = avatar->bittenEntities.begin(); i != avatar->bittenEntities.end(); i++) { - Avatar::BittenEntities::iterator i; - for (i = avatar->bittenEntities.begin(); i != avatar->bittenEntities.end(); i++) + if (e == (*i)) { - if (e == (*i)) - { - return false; - } + return false; } - return true; } - } - else - { - return false; + return true; } } else if (e->getEntityType() == ET_AVATAR) @@ -8745,7 +8727,6 @@ void Game::refreshFoodSlots(bool effects) { foodSlots[i]->refresh(effects); } - adjustFoodSlotCursor(); } void Game::refreshTreasureSlots() @@ -9977,7 +9958,7 @@ void Game::update(float dt) if (avatar) { - tintColor.update(dt); + /*tintColor.update(dt); if (core->afterEffectManager) { if (tintColor.isInterpolating()) @@ -9986,7 +9967,7 @@ void Game::update(float dt) core->afterEffectManager->setActiveShader(AS_NONE); core->afterEffectManager->glowShader.setValue(tintColor.x, tintColor.y, tintColor.z, 1); - } + }*/ if (avatar->isRolling()) particleManager->addInfluence(ParticleInfluence(avatar->position, 300, 800, true)); @@ -10724,11 +10705,6 @@ void Game::removeState() elementUpdateList.clear(); - if (core->afterEffectManager) - { - //core->afterEffectManager->blurShader.setMode(0); - core->afterEffectManager->setActiveShader(AS_NONE); - } dsq->setCursor(CURSOR_NORMAL); dsq->darkLayer.toggle(0); dsq->shakeCamera(0,0); diff --git a/Aquaria/Game.h b/Aquaria/Game.h index 33a5bc6..3585cca 100644 --- a/Aquaria/Game.h +++ b/Aquaria/Game.h @@ -714,6 +714,8 @@ public: Ingredient *getNearestIngredient(const Vector &pos, int radius); Entity *getNearestEntity(const Vector &pos, int radius, Entity *ignore = 0, EntityType et=ET_NOTYPE, DamageType dt=DT_NONE, int lrStart=-1, int lrEnd=-1); + Script *cookingScript; + void spawnManaBall(Vector pos, float a); bool updateMusic(); std::string overrideMusic; @@ -892,7 +894,8 @@ public: std::string getNoteName(int n, const std::string &pre=""); void selectEntityFromGroups(); - InterpolatedVector cameraInterp, tintColor; + InterpolatedVector cameraInterp; + //InterpolatedVector tintColor; float getWaterLevel(); void setMusicToPlay(const std::string &musicToPlay); Vector lastCollidePosition; @@ -1001,6 +1004,9 @@ public: void toggleHelpScreen(bool on, const std::string &label=""); void onToggleHelpScreen(); + void setWorldPaused(bool b) { worldPaused = b; } + bool isWorldPaused() const { return worldPaused; } + protected: void onHelpUp(); @@ -1158,6 +1164,7 @@ protected: std::vector menu; Quad *menuBg, *menuBg2; bool paused; + bool worldPaused; Vector getClosestPointOnTriangle(Vector a, Vector b, Vector c, Vector p); Vector getClosestPointOnLine(Vector a, Vector b, Vector p); diff --git a/Aquaria/GameplayVariables.cpp b/Aquaria/GameplayVariables.cpp index bd04c5d..8d7bfcd 100644 --- a/Aquaria/GameplayVariables.cpp +++ b/Aquaria/GameplayVariables.cpp @@ -27,8 +27,7 @@ void GameplayVariables::load() InStream inFile("data/variables.txt"); if(!inFile) { - core->messageBox(dsq->continuity.stringBank.get(2008), dsq->continuity.stringBank.get(2017)); - exit(1); + exit_error(dsq->continuity.stringBank.get(2017)); } std::string s; inFile >> s >> maxSlowSwimSpeed; diff --git a/Aquaria/Hair.cpp b/Aquaria/Hair.cpp index 69200da..80cc0f0 100644 --- a/Aquaria/Hair.cpp +++ b/Aquaria/Hair.cpp @@ -130,7 +130,7 @@ HairNode *Hair::getHairNode(int idx) void Hair::onRender() { #ifdef BBGE_BUILD_OPENGL - glDisable(GL_CULL_FACE); + //glDisable(GL_CULL_FACE); glBegin(GL_QUAD_STRIP); float texBits = 1.0f / (hairNodes.size()-1); @@ -192,7 +192,7 @@ void Hair::onRender() } */ - glEnable(GL_CULL_FACE); + //glEnable(GL_CULL_FACE); #endif } diff --git a/Aquaria/Ingredient.cpp b/Aquaria/Ingredient.cpp index d31d980..ef791f0 100644 --- a/Aquaria/Ingredient.cpp +++ b/Aquaria/Ingredient.cpp @@ -22,8 +22,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "Avatar.h" IngredientData::IngredientData(const std::string &name, const std::string &gfx, IngredientType type) -: name(name), gfx(gfx), amount(0), held(0), type(type), marked(0), sorted(false) +: name(name), gfx(gfx), amount(0), maxAmount(MAX_INGREDIENT_AMOUNT), held(0), type(type), marked(0), sorted(false) , displayName(dsq->continuity.getIngredientDisplayName(name)) +, rotKind(!(type == IT_OIL && type == IT_EGG)) { } @@ -83,15 +84,7 @@ void Ingredient::destroy() bool Ingredient::isRotKind() { - if (data) - { - if (data->type == IT_OIL || data->type == IT_EGG) - { - return false; - } - return true; - } - return false; + return data && data->rotKind; } IngredientData *Ingredient::getIngredientData() @@ -109,7 +102,7 @@ void Ingredient::eat(Entity *e) void Ingredient::onUpdate(float dt) { if (dsq->game->isPaused()) return; - if (dsq->continuity.getWorldType() == WT_SPIRIT) return; + if (dsq->game->isWorldPaused()) return; Vector lastPosition = position; Entity::onUpdate(dt); diff --git a/Aquaria/MiniMapRender.cpp b/Aquaria/MiniMapRender.cpp index 095db91..77e6668 100644 --- a/Aquaria/MiniMapRender.cpp +++ b/Aquaria/MiniMapRender.cpp @@ -258,11 +258,18 @@ void MiniMapRender::onUpdate(float dt) if (dsq->darkLayer.isUsed() && dsq->game->avatar) { - if (dsq->continuity.form != FORM_SUN && dsq->game->avatar->isInDarkness()) + const SeeMapMode mapmode = dsq->game->avatar->getSeeMapMode(); + + if(mapmode == SEE_MAP_ALWAYS) + radarHide = false; + else if(mapmode == SEE_MAP_NEVER) + radarHide = true; + else if (dsq->continuity.form != FORM_SUN && dsq->game->avatar->isInDarkness()) { radarHide = true; } - else + + if(!radarHide) { for (Path *p = dsq->game->getFirstPathOfType(PATH_RADARHIDE); p; p = p->nextOfType) { @@ -273,6 +280,7 @@ void MiniMapRender::onUpdate(float dt) } } } + float t = dt*2; if (radarHide) { diff --git a/Aquaria/Mod.cpp b/Aquaria/Mod.cpp index 693b9f0..4a38b9c 100644 --- a/Aquaria/Mod.cpp +++ b/Aquaria/Mod.cpp @@ -39,6 +39,11 @@ Mod::Mod() shuttingDown = false; } +Mod::~Mod() +{ + modcache.clean(); +} + /* queue for actual stop and recache which happens in game::applystate @@ -182,6 +187,23 @@ void Mod::recache() core->resetTimer(); } + + if(active) + { + modcache.setBaseDir(dsq->secondaryTexturePath); + std::string fname = path; + if(fname[fname.length() - 1] != '/') + fname += '/'; + fname += "precache.txt"; + fname = localisePath(fname, dsq->mod.getPath()); + fname = core->adjustFilenameCase(fname); + if (exists(fname)) + modcache.precacheList(fname); + } + else + { + modcache.clean(); + } } void Mod::start() @@ -284,6 +306,7 @@ void Mod::stop() debugMenu = false; shuttingDown = false; dsq->scriptInterface.reset(); + dsq->game->setWorldPaused(false); } void Mod::update(float dt) diff --git a/Aquaria/Path.cpp b/Aquaria/Path.cpp index 41da549..400d4b4 100644 --- a/Aquaria/Path.cpp +++ b/Aquaria/Path.cpp @@ -53,12 +53,7 @@ Path::Path() spawnEnemyNumber = 0; spawnEnemyDistance = 0; warpType = 0; - /* - rect.x1 = -10; - rect.x2 = 20; - rect.y1 = -256; - rect.y2 = 256; - */ + spiritFreeze = true; } void Path::clampPosition(Vector *pos, int radius) @@ -484,7 +479,7 @@ void Path::init() void Path::update(float dt) { - if (!dsq->game->isPaused() && dsq->continuity.getWorldType() == WT_NORMAL) + if (!dsq->game->isPaused() && !(spiritFreeze && dsq->game->isWorldPaused())) { if (addEmitter && emitter) { @@ -523,7 +518,7 @@ void Path::update(float dt) { spawnedEntity = 0; } - if (pathType == PATH_CURRENT && dsq->continuity.getWorldType() == WT_NORMAL) + if (pathType == PATH_CURRENT && !dsq->game->isWorldPaused()) { animOffset -= currentMod*(dt/830); /* @@ -559,7 +554,7 @@ void Path::update(float dt) } } - if (pathType == PATH_STEAM && dsq->continuity.getWorldType() == WT_NORMAL && effectOn) + if (pathType == PATH_STEAM && !dsq->game->isWorldPaused() && effectOn) { animOffset -= 1000*0.00002f; diff --git a/Aquaria/Path.h b/Aquaria/Path.h index b3369a2..8087008 100644 --- a/Aquaria/Path.h +++ b/Aquaria/Path.h @@ -143,6 +143,7 @@ public: std::string gem; bool effectOn; + bool spiritFreeze; PathShape pathShape; diff --git a/Aquaria/SceneEditor.cpp b/Aquaria/SceneEditor.cpp index ae8dc7a..cf173fb 100644 --- a/Aquaria/SceneEditor.cpp +++ b/Aquaria/SceneEditor.cpp @@ -3578,10 +3578,10 @@ void SceneEditor::update(float dt) (dsq->getGameCursorPosition().y - cursorOffset.y)*factor); //editingElement->scale=oldScale + add; Vector sz = oldScale + add; - if (sz.x < 64) - sz.x = 64; - if (sz.y < 64) - sz.y = 64; + if (sz.x < 32) + sz.x = 32; + if (sz.y < 32) + sz.y = 32; editingPath->rect.x1 = -sz.x/2; editingPath->rect.x2 = sz.x/2; editingPath->rect.y1 = -sz.y/2; diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index 0714f94..cb51bf3 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -76,6 +76,7 @@ static const char * const interfaceFunctions[] = { "activate", "animationKey", "castSong", + "cookFailure", "damage", "deathNotify", "dieEaten", @@ -84,6 +85,7 @@ static const char * const interfaceFunctions[] = { "entityDied", "exitState", "exitTimer", + "getIngredientString", "hitEntity", "hitSurface", "init", @@ -98,6 +100,7 @@ static const char * const interfaceFunctions[] = { "songNoteDone", "sporesDropped", "update", + "useIngredient", "useTreasure", NULL }; @@ -361,7 +364,7 @@ static void scriptError(lua_State *L, const std::string& msg) // - The C++ standard allows offsetof() only on POD-types. Oh well, it probably works anyways. // If it does not compile for some reason, comment it out, hope for the best, and go ahead. #if !(defined(__GNUC__) && __GNUC__ <= 2) -void compile_time_assertions() +static void compile_time_assertions() { #define oo(cls) offsetof(cls, _objtype) compile_assert(oo(Path) == oo(RenderObject)); @@ -377,6 +380,7 @@ void compile_time_assertions() compile_assert(oo(Path) == oo(Quad)); compile_assert(oo(Path) == oo(Avatar)); compile_assert(oo(Path) == oo(BaseText)); + compile_assert(oo(Path) == oo(PauseQuad)); #undef oo } #endif @@ -457,6 +461,12 @@ std::string getString(lua_State *L, int slot = 1) return sr; } +static inline +const char *getCString(lua_State *L, int slot = 1) +{ + return lua_isstring(L, slot) ? lua_tostring(L, slot) : NULL; +} + static inline Shot *getShot(lua_State *L, int slot = 1) { @@ -578,6 +588,16 @@ BaseText *getText(lua_State *L, int slot = 1) return q; } +static inline +Shader *getShader(lua_State *L, int slot = 1) +{ + Shader *q = (Shader*)lua_touserdata(L, slot); + ENSURE_TYPE(q, SCO_SHADER); + if (!q) + scriptDebug(L, "Invalid Shader"); + return q; +} + static SkeletalSprite *getSkeletalSprite(Entity *e) { return e ? &e->skeletalSprite : NULL; @@ -693,8 +713,8 @@ luaFunc(indexWarnInstance) luaFunc(panicHandler) { - errorLog(luaFormatStackInfo(L) + ": Lua PANIC: " + getString(L, -1)); - exit(1); + std::string err = luaFormatStackInfo(L) + ": Lua PANIC: " + getString(L, -1); + exit_error(err); } static bool findFile_helper(const char *rawname, std::string &fname) @@ -847,6 +867,12 @@ luaFunc(obj_alphaMod) luaReturnNil() } +luaFunc(obj_getAlphaMod) +{ + RenderObject *r = robj(L); + luaReturnNum(r ? r->alphaMod : 0.0f); +} + luaFunc(obj_getAlpha) { RenderObject *r = robj(L); @@ -865,6 +891,16 @@ luaFunc(obj_color) luaReturnNil(); } +luaFunc(obj_getColor) +{ + RenderObject *r = robj(L); + Vector c; + if(r) + c = r->color; + luaReturnVec3(c.x, c.y, c.z); +} + + luaFunc(obj_rotate) { RenderObject *r = robj(L); @@ -1517,7 +1553,9 @@ luaFunc(quad_setSegs) RO_FUNC(getter, prefix, alpha ) \ RO_FUNC(getter, prefix, alphaMod ) \ RO_FUNC(getter, prefix, getAlpha ) \ + RO_FUNC(getter, prefix, getAlphaMod ) \ RO_FUNC(getter, prefix, color ) \ + RO_FUNC(getter, prefix, getColor ) \ RO_FUNC(getter, prefix, rotate ) \ RO_FUNC(getter, prefix, rotateOffset ) \ RO_FUNC(getter, prefix, getRotation ) \ @@ -1579,6 +1617,7 @@ luaFunc(quad_setSegs) RO_FUNC(getter, prefix, disableMotionBlur ) \ RO_FUNC(getter, prefix, collideCircleVsLine) \ RO_FUNC(getter, prefix, collideCircleVsLineAngle) \ + RO_FUNC(getter, prefix, getVectorToObj ) \ MK_ALIAS(prefix, fh, flipHorizontal ) \ MK_ALIAS(prefix, fv, flipVertical ) @@ -2112,18 +2151,22 @@ luaFunc(entity_setRidingData) luaFunc(entity_setBoneLock) { Entity *e = entity(L); - Entity *e2 = entity(L, 2); - Bone *b = 0; - if (lua_isuserdata(L, 3)) - b = bone(L, 3); bool ret = false; if (e) { BoneLock bl; - bl.entity = e2; - bl.bone = b; - bl.on = true; - bl.collisionMaskIndex = dsq->game->lastCollideMaskIndex; + if (lua_isuserdata(L, 2)) + { + Entity *e2 = entity(L, 2); + Bone *b = 0; + if (lua_isuserdata(L, 3)) + b = bone(L, 3); + + bl.entity = e2; + bl.bone = b; + bl.on = true; + bl.collisionMaskIndex = dsq->game->lastCollideMaskIndex; + } ret = e->setBoneLock(bl); } luaReturnBool(ret); @@ -2347,6 +2390,25 @@ luaFunc(getWorldType) luaReturnNum((int)dsq->continuity.getWorldType()); } +luaFunc(setWorldType) +{ + WorldType wt = (WorldType)lua_tointeger(L, 1); + bool trans = getBool(L, 2); + dsq->continuity.applyWorldEffects(wt, trans, 1); // last arg is not used + luaReturnNil(); +} + +luaFunc(isWorldPaused) +{ + luaReturnBool(dsq->game->isWorldPaused()); +} + +luaFunc(setWorldPaused) +{ + dsq->game->setWorldPaused(getBool(L, 1)); + luaReturnNil(); +} + luaFunc(getNearestNodeByType) { int x = lua_tonumber(L, 1); @@ -2542,6 +2604,14 @@ luaFunc(entity_setSpiritFreeze) luaReturnNil(); } +luaFunc(node_setSpiritFreeze) +{ + Path *e = path(L); + if (e) + e->spiritFreeze = getBool(L,2); + luaReturnNil(); +} + luaFunc(entity_setFillGrid) { Entity *e = entity(L); @@ -2553,6 +2623,12 @@ luaFunc(entity_setFillGrid) luaReturnNil(); } +luaFunc(entity_isFillGrid) +{ + Entity *e = entity(L); + luaReturnBool(e ? e->fillGridFromQuad : false); +} + luaFunc(entity_getAimVector) { Entity *e = entity(L); @@ -2679,6 +2755,69 @@ luaFunc(avatar_setCanDie) luaReturnNil(); } +// not naming this avatar_* because it rather belongs into the UI category... +luaFunc(setCanActivate) +{ + dsq->game->avatar->setCanActivateStuff(getBool(L, 1)); + luaReturnNil(); +} + +luaFunc(setSeeMapMode) +{ + dsq->game->avatar->setSeeMapMode((SeeMapMode)lua_tointeger(L, 1)); + luaReturnNil(); +} + +luaFunc(avatar_setCanBurst) +{ + dsq->game->avatar->setCanBurst(getBool(L, 1)); + luaReturnNil(); +} + +luaFunc(avatar_canBurst) +{ + luaReturnBool(dsq->game->avatar->canBurst()); +} + +luaFunc(avatar_setCanLockToWall) +{ + dsq->game->avatar->setCanLockToWall(getBool(L, 1)); + luaReturnNil(); +} + +luaFunc(avatar_canLockToWall) +{ + luaReturnBool(dsq->game->avatar->canLockToWall()); +} + +luaFunc(avatar_setCanSwimAgainstCurrents) +{ + dsq->game->avatar->setCanSwimAgainstCurrents(getBool(L, 1)); + luaReturnNil(); +} + +luaFunc(avatar_canSwimAgainstCurrents) +{ + luaReturnBool(dsq->game->avatar->canSwimAgainstCurrents()); +} + +luaFunc(avatar_setCanCollideWithShots) +{ + dsq->game->avatar->setCollideWithShots(getBool(L, 1)); + luaReturnNil(); +} + +luaFunc(avatar_canCollideWithShots) +{ + luaReturnBool(dsq->game->avatar->canCollideWithShots()); +} + +luaFunc(avatar_setCollisionAvoidanceData) +{ + dsq->game->avatar->setCollisionAvoidanceData(lua_tointeger(L, 1), lua_tonumber(L, 2)); + luaReturnNil(); +} + luaFunc(avatar_toggleCape) { dsq->game->avatar->toggleCape(getBool(L,1)); @@ -2693,6 +2832,11 @@ luaFunc(avatar_setBlockSinging) luaReturnNil(); } +luaFunc(avatar_isBlockSinging) +{ + luaReturnBool(dsq->game->avatar->isBlockSinging()); +} + luaFunc(avatar_fallOffWall) { dsq->game->avatar->fallOffWall(); @@ -2726,6 +2870,16 @@ luaFunc(avatar_isShieldActive) luaReturnBool(v); } +luaFunc(avatar_setShieldActive) +{ + bool on = getBool(L, 1); + if (on) + dsq->game->avatar->activateAura(AURA_SHIELD); + else + dsq->game->avatar->stopAura(); + luaReturnNil(); +} + luaFunc(avatar_getStillTimer) { luaReturnNum(dsq->game->avatar->stillTimer.getValue()); @@ -2744,6 +2898,28 @@ luaFunc(avatar_getSpellCharge) luaReturnNum(dsq->game->avatar->state.spellCharge); } +luaFunc(avatar_setSpeedMult) +{ + dsq->continuity.setSpeedMultiplier(lua_tonumber(L, 1), lua_tonumber(L, 2)); + luaReturnNil(); +} + +luaFunc(avatar_setSpeedMult2) +{ + dsq->continuity.speedMult2 = lua_tonumber(L, 1); + luaReturnNil(); +} + +luaFunc(avatar_getSpeedMult) +{ + luaReturnNum(dsq->continuity.speedMult); +} + +luaFunc(avatar_getSpeedMult2) +{ + luaReturnNum(dsq->continuity.speedMult2); +} + luaFunc(jumpState) { dsq->enqueueJumpState(getString(L, 1), getBool(L, 2)); @@ -2846,11 +3022,6 @@ luaFunc(entity_followPath) luaReturnNil(); } -luaFunc(getIngredientGfx) -{ - luaReturnStr(dsq->continuity.getIngredientGfx(getString(L, 1)).c_str()); -} - luaFunc(spawnIngredient) { int times = lua_tonumber(L, 4); @@ -2887,6 +3058,27 @@ luaFunc(spawnParticleEffect) luaReturnPtr(pe); } +luaFunc(setNumSuckPositions) +{ + particleManager->setNumSuckPositions(lua_tointeger(L, 1)); + luaReturnNil(); +} + +luaFunc(setSuckPosition) +{ + particleManager->setSuckPosition(lua_tointeger(L, 1), Vector(lua_tonumber(L, 2), lua_tonumber(L, 3))); + luaReturnNil(); +} + +luaFunc(getSuckPosition) +{ + Vector *v = particleManager->getSuckPosition(lua_tointeger(L, 1)); + if(v) + luaReturnVec2(v->x, v->y); + luaReturnVec2(0.0f, 0.0f); +} + + luaFunc(bone_showFrame) { Bone *b = bone(L); @@ -3038,6 +3230,11 @@ luaFunc(entity_checkSplash) luaReturnBool(ret); } +luaFunc(entity_isInCurrent) +{ + Entity *e = entity(L); + luaReturnBool(e ? e->isInCurrent() : false); +} luaFunc(entity_isUnderWater) { @@ -3612,6 +3809,16 @@ luaFunc(beam_setDamage) luaReturnNil(); } +luaFunc(beam_setDamageType) +{ + Beam *b = beam(L); + if (b) + { + b->damageData.damageType = (DamageType)lua_tointeger(L, 2); + } + luaReturnNil(); +} + luaFunc(beam_setBeamWidth) { Beam *b = beam(L); @@ -3741,6 +3948,12 @@ luaFunc(setSceneColor) luaReturnNil(); } +luaFunc(getSceneColor) +{ + const Vector& c = dsq->game->sceneColor3; + luaReturnVec3(c.x, c.y, c.z); +} + luaFunc(setCameraLerpDelay) { dsq->game->cameraLerpDelay = lua_tonumber(L, 1); @@ -3806,6 +4019,8 @@ luaFunc(entity_damage) d.attacker = lua_isuserdata(L, 2) ? entity(L, 2) : NULL; d.damage = lua_tonumber(L, 3); d.damageType = (DamageType)lua_tointeger(L, 4); + d.effectTime = lua_tonumber(L, 5); + d.useTimer = !getBool(L, 6); didDamage = e->damage(d); } luaReturnBool(didDamage); @@ -4577,6 +4792,18 @@ luaFunc(entity_getDistanceToTarget) luaReturnNum(dist); } +luaFunc(entity_getDistanceToPoint) +{ + Entity *e = entity(L); + float dist = 0; + if (e) + { + Vector p(lua_tonumber(L, 2), lua_tonumber(L, 3)); + dist = (p - e->position).getLength2D(); + } + luaReturnNum(dist); +} + luaFunc(entity_watchEntity) { Entity *e = entity(L); @@ -4731,6 +4958,15 @@ luaFunc(createQuad) luaReturnPtr(q); } +luaFunc(quad_setPauseLevel) +{ + Quad *q = getQuad(L); + ENSURE_TYPE(q, SCO_PAUSEQUAD); + if (q) + ((PauseQuad*)q)->pauseLevel = lua_tointeger(L, 2); + luaReturnNil(); +} + luaFunc(setupEntity) { ScriptedEntity *se = scriptedEntity(L); @@ -5045,6 +5281,12 @@ luaFunc(entity_setMaxSpeedLerp) luaReturnNil(); } +luaFunc(entity_getMaxSpeedLerp) +{ + Entity *e = entity(L); + luaReturnNum(e ? e->maxSpeedLerp.x : 0.0f); +} + // note: this is a weaker setState than perform // this is so that things can override it // for example getting PUSH-ed (Force) or FROZEN (bubbled) @@ -5217,6 +5459,12 @@ luaFunc(entity_setDeathScene) luaReturnNil(); } +luaFunc(entity_isDeathScene) +{ + Entity *e = entity(L); + luaReturnBool(e ? e->isDeathScene() : false); +} + luaFunc(entity_setCurrentTarget) { Entity *e = entity(L); @@ -5388,6 +5636,12 @@ luaFunc(entity_getRandomTargetPoint) luaReturnNum(idx); } +luaFunc(entity_getNumTargetPoints) +{ + Entity *e = entity(L); + luaReturnInt(e ? e->getNumTargetPoints() : 0); +} + luaFunc(playVisualEffect) { Entity *target = NULL; @@ -6155,6 +6409,12 @@ luaFunc(entity_getDistanceToEntity) luaReturnNum(d); } +luaFunc(entity_isEntityInside) +{ + Entity *e = entity(L); + luaReturnBool(e ? e->isEntityInside() : false); +} + // entity_istargetInRange luaFunc(entity_isTargetInRange) { @@ -6499,6 +6759,13 @@ luaFunc(ing_hasIET) luaReturnBool(has); } +luaFunc(ing_getIngredientName) +{ + Ingredient *i = getIng(L, 1); + IngredientData *data = i ? i->getIngredientData() : 0; + luaReturnStr(data ? data->name.c_str() : ""); +} + luaFunc(entity_getNearestEntity) { Entity *me = entity(L); @@ -6559,6 +6826,20 @@ luaFunc(entity_getNearestEntity) luaReturnPtr(closest); } +luaFunc(getNearestEntity) +{ + Vector p(lua_tonumber(L, 1), lua_tonumber(L, 2)); + int radius = lua_tointeger(L, 3); + Entity *ignore = lua_isuserdata(L, 4) ? entity(L, 4) : NULL; + EntityType et = lua_isnumber(L, 5) ? (EntityType)lua_tointeger(L, 5) : ET_NOTYPE; + DamageType dt = lua_isnumber(L, 6) ? (DamageType)lua_tointeger(L, 6) : DT_NONE; + int lrStart = lua_isnumber(L, 7) ? lua_tointeger(L, 7) : -1; + int lrEnd = lua_isnumber(L, 8) ? lua_tointeger(L, 8) : -1; + + Entity *target = dsq->game->getNearestEntity(p, radius, ignore, ET_ENEMY, dt, lrStart, lrEnd); + luaReturnPtr(target); +} + luaFunc(findWall) { int x = lua_tonumber(L, 1); @@ -6755,7 +7036,7 @@ luaFunc(entity_getHair) luaFunc(entity_clearHair) { Entity *e = entity(L); - if (e) + if (e && e->hair) { e->hair->safeKill(); e->hair = 0; @@ -7062,21 +7343,21 @@ luaFunc(getMouseWorldPos) luaFunc(fade) { - dsq->overlay->color = Vector(lua_tonumber(L, 3), lua_tonumber(L, 4), lua_tonumber(L, 5)); + dsq->overlay->color.interpolateTo(Vector(lua_tonumber(L, 3), lua_tonumber(L, 4), lua_tonumber(L, 5)), lua_tonumber(L, 6)); dsq->overlay->alpha.interpolateTo(lua_tonumber(L, 1), lua_tonumber(L, 2)); luaReturnNil(); } luaFunc(fade2) { - dsq->overlay2->color = Vector(lua_tonumber(L, 3), lua_tonumber(L, 4), lua_tonumber(L, 5)); + dsq->overlay2->color.interpolateTo(Vector(lua_tonumber(L, 3), lua_tonumber(L, 4), lua_tonumber(L, 5)), lua_tonumber(L, 6)); dsq->overlay2->alpha.interpolateTo(lua_tonumber(L, 1), lua_tonumber(L, 2)); luaReturnNil(); } luaFunc(fade3) { - dsq->overlay3->color = Vector(lua_tonumber(L, 3), lua_tonumber(L, 4), lua_tonumber(L, 5)); + dsq->overlay3->color.interpolateTo(Vector(lua_tonumber(L, 3), lua_tonumber(L, 4), lua_tonumber(L, 5)), lua_tonumber(L, 6)); dsq->overlay3->alpha.interpolateTo(lua_tonumber(L, 1), lua_tonumber(L, 2)); luaReturnNil(); } @@ -7461,6 +7742,82 @@ luaFunc(getScreenSize) luaReturnVec2(core->width, core->height); } +luaFunc(inv_isFull) +{ + IngredientData *data = dsq->continuity.getIngredientDataByName(getString(L, 1)); + bool full = false; + if(data) + full = dsq->continuity.isIngredientFull(data); + luaReturnBool(full); +} + +luaFunc(inv_getMaxAmount) +{ + IngredientData *data = dsq->continuity.getIngredientDataByName(getString(L, 1)); + luaReturnInt(data ? data->maxAmount : 0); +} + +luaFunc(inv_getAmount) +{ + IngredientData *data = dsq->continuity.getIngredientDataByName(getString(L, 1)); + luaReturnInt(data ? data->amount : 0); +} + +luaFunc(inv_add) +{ + IngredientData *data = dsq->continuity.getIngredientDataByName(getString(L, 1)); + if(data) + dsq->continuity.pickupIngredient(data, lua_tointeger(L, 2), false, false); + luaReturnNil(); +} + +luaFunc(inv_getGfx) +{ + luaReturnStr(dsq->continuity.getIngredientGfx(getString(L, 1)).c_str()); +} + +luaFunc(inv_remove) +{ + IngredientData *data = dsq->continuity.getIngredientDataByName(getString(L, 1)); + if(data && data->amount > 0) + { + data->amount--; + dsq->game->dropIngrNames.push_back(data->name); + dsq->continuity.removeEmptyIngredients(); + if(dsq->game->isInGameMenu()) + dsq->game->refreshFoodSlots(true); + } + luaReturnNil(); +} + +luaFunc(inv_getType) +{ + IngredientData *data = dsq->continuity.getIngredientDataByName(getString(L, 1)); + luaReturnInt(data ? data->type : 0); +} + +luaFunc(inv_getDisplayName) +{ + IngredientData *data = dsq->continuity.getIngredientDataByName(getString(L, 1)); + luaReturnStr(data ? data->displayName.c_str() : ""); +} + +luaFunc(inv_pickupEffect) +{ + IngredientData *data = dsq->continuity.getIngredientDataByName(getString(L, 1)); + if(data) + dsq->game->pickupIngredientEffects(data); + luaReturnNil(); +} + +luaFunc(learnRecipe) +{ + std::string name = getString(L, 1); + bool show = getBool(L, 2); + dsq->continuity.learnRecipe(name, show); + luaReturnNil(); +} + luaFunc(createDebugText) { DebugFont *txt = new DebugFont(lua_tointeger(L, 2), getString(L, 1)); @@ -7504,6 +7861,81 @@ luaFunc(text_setWidth) luaReturnNil(); } +luaFunc(loadShader) +{ + int handle = 0; + const char *vertRaw = getCString(L, 1); + const char *fragRaw = getCString(L, 2); + std::string vert, frag; + if(vertRaw) + findFile_helper(vertRaw, vert); + if(fragRaw) + findFile_helper(fragRaw, frag); + + if(core->afterEffectManager) + handle = core->afterEffectManager->loadShaderFile(vert.c_str(), frag.c_str()); + + luaReturnInt(handle); +} + +luaFunc(createShader) +{ + int handle = 0; + if(core->afterEffectManager) + handle = core->afterEffectManager->loadShaderSrc(getCString(L, 1), getCString(L, 2)); + luaReturnInt(handle); +} + +luaFunc(shader_setAsAfterEffect) +{ + int handle = lua_tointeger(L, 1); + int pos = lua_tointeger(L, 2); + bool done = false; + + if(core->afterEffectManager) + done = core->afterEffectManager->setShaderPipelinePos(handle, pos); + + luaReturnBool(done); +} + +luaFunc(shader_setNumAfterEffects) +{ + if(core->afterEffectManager) + core->afterEffectManager->setShaderPipelineSize(lua_tointeger(L, 1)); + luaReturnNil(); +} + +luaFunc(shader_setInt) +{ + if(core->afterEffectManager) + { + Shader *sh = core->afterEffectManager->getShaderPtr(lua_tointeger(L, 1)); + const char *name = getCString(L, 2); + if(sh && name) + sh->setInt(name, lua_tointeger(L, 3), lua_tointeger(L, 4), lua_tointeger(L, 5), lua_tointeger(L, 6)); + } + luaReturnNil(); +} + +luaFunc(shader_setFloat) +{ + if(core->afterEffectManager) + { + Shader *sh = core->afterEffectManager->getShaderPtr(lua_tointeger(L, 1)); + const char *name = getCString(L, 2); + if(sh && name) + sh->setFloat(name, lua_tonumber(L, 3), lua_tonumber(L, 4), lua_tonumber(L, 5), lua_tonumber(L, 6)); + } + luaReturnNil(); +} + +luaFunc(shader_delete) +{ + if(core->afterEffectManager) + core->afterEffectManager->unloadShader(lua_tointeger(L, 1)); + luaReturnNil(); +} + //-------------------------------------------------------------------------------------------- @@ -7541,11 +7973,15 @@ static const struct { luaRegister(getNoteName), luaRegister(getWorldType), + luaRegister(setWorldType), + luaRegister(setWorldPaused), + luaRegister(isWorldPaused), luaRegister(getWaterLevel), luaRegister(setWaterLevel), luaRegister(createQuad), + luaRegister(quad_setPauseLevel), luaRegister(setupEntity), luaRegister(setActivePet), @@ -7554,6 +7990,7 @@ static const struct { luaRegister(reconstructEntityGrid), luaRegister(ing_hasIET), + luaRegister(ing_getIngredientName), luaRegister(esetv), luaRegister(esetvf), @@ -7570,6 +8007,7 @@ static const struct { luaRegister(entity_setBoneLock), luaRegister(entity_setIngredient), luaRegister(entity_setDeathScene), + luaRegister(entity_isDeathScene), luaRegister(entity_setBeautyFlip), luaRegister(entity_setInvincible), @@ -7594,6 +8032,7 @@ static const struct { luaRegister(entity_setEatType), luaRegister(entity_setSpiritFreeze), + luaRegister(node_setSpiritFreeze), luaRegister(entity_setCanLeaveWater), @@ -7614,9 +8053,20 @@ static const struct { luaRegister(avatar_setCanDie), + luaRegister(setCanActivate), + luaRegister(setSeeMapMode), luaRegister(avatar_toggleCape), luaRegister(avatar_setPullTarget), + luaRegister(avatar_setCanLockToWall), + luaRegister(avatar_canLockToWall), + luaRegister(avatar_setCanBurst), + luaRegister(avatar_canBurst), + luaRegister(avatar_setCanSwimAgainstCurrents), + luaRegister(avatar_canSwimAgainstCurrents), + luaRegister(avatar_setCanCollideWithShots), + luaRegister(avatar_canCollideWithShots), + luaRegister(avatar_setCollisionAvoidanceData), luaRegister(avatar_clampPosition), luaRegister(avatar_updatePosition), @@ -7649,9 +8099,11 @@ static const struct { luaRegister(entity_isUnderWater), luaRegister(entity_checkSplash), + luaRegister(entity_isInCurrent), luaRegister(entity_getRandomTargetPoint), luaRegister(entity_getTargetPoint), + luaRegister(entity_getNumTargetPoints), luaRegister(entity_setTargetRange), @@ -7676,6 +8128,7 @@ static const struct { luaRegister(beam_setDamage), luaRegister(beam_setBeamWidth), luaRegister(beam_setFirer), + luaRegister(beam_setDamageType), luaRegister(getStringBank), @@ -7721,6 +8174,7 @@ static const struct { luaRegister(entity_getVectorToEntity), luaRegister(entity_getDistanceToTarget), + luaRegister(entity_getDistanceToPoint), luaRegister(entity_move), luaRegister(entity_getID), @@ -7818,6 +8272,7 @@ static const struct { luaRegister(entity_isTargetInRange), luaRegister(entity_getDistanceToEntity), + luaRegister(entity_isEntityInside), luaRegister(entity_isInvincible), @@ -7834,6 +8289,7 @@ static const struct { luaRegister(entity_setMaxSpeed), luaRegister(entity_getMaxSpeed), luaRegister(entity_setMaxSpeedLerp), + luaRegister(entity_getMaxSpeedLerp), luaRegister(entity_setState), luaRegister(entity_getState), luaRegister(entity_getEnqueuedState), @@ -7857,8 +8313,6 @@ static const struct { luaRegister(registerSporeDrop), - luaRegister(getIngredientGfx), - luaRegister(spawnIngredient), luaRegister(spawnAllIngredients), luaRegister(spawnParticleEffect), @@ -7869,6 +8323,9 @@ static const struct { luaRegister(resetTimer), luaRegister(addInfluence), + luaRegister(setSuckPosition), + luaRegister(setSuckPosition), + luaRegister(setNumSuckPositions), luaRegister(setupBasicEntity), luaRegister(playMusic), luaRegister(playMusicStraight), @@ -8024,10 +8481,17 @@ static const struct { luaRegister(avatar_isRolling), luaRegister(avatar_isOnWall), luaRegister(avatar_isShieldActive), + luaRegister(avatar_setShieldActive), luaRegister(avatar_getRollDirection), luaRegister(avatar_fallOffWall), luaRegister(avatar_setBlockSinging), + luaRegister(avatar_isBlockSinging), + + luaRegister(avatar_setSpeedMult), + luaRegister(avatar_setSpeedMult2), + luaRegister(avatar_getSpeedMult), + luaRegister(avatar_getSpeedMult2), luaRegister(avatar_toggleMovement), @@ -8223,7 +8687,7 @@ static const struct { luaRegister(setSceneColor), - + luaRegister(getSceneColor), luaRegister(entity_watchEntity), @@ -8251,6 +8715,7 @@ static const struct { luaRegister(entity_setTexture), luaRegister(entity_setFillGrid), + luaRegister(entity_isFillGrid), luaRegister(entity_push), @@ -8315,6 +8780,7 @@ static const struct { luaRegister(entity_getNearestEntity), luaRegister(entity_getNearestBoneToPosition), + luaRegister(getNearestEntity), luaRegister(entity_getNearestNode), luaRegister(entity_setPoison), @@ -8344,12 +8810,31 @@ static const struct { luaRegister(getScreenVirtualOff), luaRegister(getScreenSize), + luaRegister(inv_isFull), + luaRegister(inv_getMaxAmount), + luaRegister(inv_getAmount), + luaRegister(inv_add), + luaRegister(inv_getGfx), + luaRegister(inv_remove), + luaRegister(inv_getType), + luaRegister(inv_getDisplayName), + luaRegister(inv_pickupEffect), + luaRegister(learnRecipe), + luaRegister(createDebugText), luaRegister(createBitmapText), luaRegister(text_setText), luaRegister(text_setFontSize), luaRegister(text_setWidth), + luaRegister(loadShader), + luaRegister(createShader), + luaRegister(shader_setAsAfterEffect), + luaRegister(shader_setNumAfterEffects), + luaRegister(shader_setFloat), + luaRegister(shader_setInt), + luaRegister(shader_delete), + luaRegister(isQuad), luaRegister(isNode), luaRegister(isObject), @@ -8392,6 +8877,7 @@ static const struct { {"entity_rotateTo", l_entity_rotate}, {"entity_setColor", l_entity_color}, {"entity_setInternalOffset", l_entity_internalOffset}, + {"getIngredientGfx", l_inv_getGfx}, {"bone_setColor", l_bone_color}, @@ -9033,6 +9519,7 @@ static const struct { luaConstant(DT_CRUSH), luaConstant(DT_SPIKES), luaConstant(DT_STEAM), + luaConstant(DT_WALLHURT), luaConstant(FRAME_TIME), @@ -9060,6 +9547,10 @@ static const struct { luaConstant(OT_INVISIBLEIN), luaConstant(OT_HURT), luaConstant(OT_INVISIBLEENT), + + luaConstant(SEE_MAP_NEVER), + luaConstant(SEE_MAP_DEFAULT), + luaConstant(SEE_MAP_ALWAYS), }; //============================================================================================ @@ -9613,6 +10104,41 @@ bool Script::call(const char *name, void *param1, void *param2, void *param3, fl return true; } +bool Script::call(const char *name, const char *param, bool *ret) +{ + lookupFunc(name); + lua_pushstring(L, param); + if (!doCall(1, 1)) + return false; + *ret = lua_toboolean(L, -1); + lua_pop(L, 1); + return true; +} + +bool Script::call(const char *name, const char *param, std::string *ret) +{ + lookupFunc(name); + lua_pushstring(L, param); + if (!doCall(1, 1)) + return false; + *ret = getString(L, -1); + lua_pop(L, 1); + return true; +} + +bool Script::call(const char *name, const char *param1, const char *param2, const char *param3, std::string *ret) +{ + lookupFunc(name); + lua_pushstring(L, param1); + lua_pushstring(L, param2); + lua_pushstring(L, param3); + if (!doCall(3, 1)) + return false; + *ret = getString(L, -1); + lua_pop(L, 1); + return true; +} + int Script::callVariadic(const char *name, lua_State *fromL, int nparams, void *param) { int oldtop = lua_gettop(L); diff --git a/Aquaria/ScriptInterface.h b/Aquaria/ScriptInterface.h index bf23dca..2815764 100644 --- a/Aquaria/ScriptInterface.h +++ b/Aquaria/ScriptInterface.h @@ -60,6 +60,12 @@ public: bool call(const char *name, void *param1, void *param2, void *param3, void *param4); // boolean = function(pointer, pointer, pointer, number, number, number, number, pointer) bool call(const char *name, void *param1, void *param2, void *param3, float param4, float param5, float param6, float param7, void *param8, bool *ret1); + // boolean = function(string) + bool call(const char *name, const char *param, bool *ret); + // string = function(string) + bool call(const char *name, const char *param, std::string *ret); + // string = function(string, string, string) + bool call(const char *name, const char *param1, const char *param2, const char *param3, std::string *ret); // function(pointer, ...) - anything that is already on the stack is forwarded. Results are left on the stack. // Returns how many values the called function returned, or -1 in case of error. int callVariadic(const char *name, lua_State *L, int nparams, void *param); diff --git a/Aquaria/ScriptedEntity.cpp b/Aquaria/ScriptedEntity.cpp index 67aa2a1..10f4c9e 100644 --- a/Aquaria/ScriptedEntity.cpp +++ b/Aquaria/ScriptedEntity.cpp @@ -759,32 +759,6 @@ void ScriptedEntity::songNoteDone(int note, float len) } } -bool ScriptedEntity::isEntityInside() -{ - bool v = false; - int avatars = 0; - FOR_ENTITIES(i) - { - Entity *e = *i; - if (e->getEntityType() == ET_AVATAR) - avatars ++; - if (e && e->life == 1 && e != this && e->ridingOnEntity != this) - { - if (isCoordinateInside(e->position)) - { - /* - Vector diff = (e->position - position); - diff.setLength2D(100); - e->vel += diff; - */ - v = true; - } - } - - } - return v; -} - void ScriptedEntity::becomeSolid() { //vel = 0; diff --git a/Aquaria/ScriptedEntity.h b/Aquaria/ScriptedEntity.h index 3c13dc7..f943f6a 100644 --- a/Aquaria/ScriptedEntity.h +++ b/Aquaria/ScriptedEntity.h @@ -68,7 +68,6 @@ public: typedef std::vector Strands; Strands strands; int strandSpacing; - bool isEntityInside(); void becomeSolid(); std::string deathParticleEffect; diff --git a/Aquaria/Shot.cpp b/Aquaria/Shot.cpp index b52b762..757b041 100644 --- a/Aquaria/Shot.cpp +++ b/Aquaria/Shot.cpp @@ -342,6 +342,7 @@ Shot::Shot() : Quad(), Segmented(0,0) fired = false; target = 0; dead = false; + enqueuedForDelete = false; shotIdx = shots.size(); shots.push_back(this); } @@ -487,7 +488,6 @@ void Shot::setLifeTime(float l) void Shot::onEndOfLife() { destroySegments(0.2); - deleteShots.push_back(this); dead = true; if (emitter) @@ -495,6 +495,12 @@ void Shot::onEndOfLife() emitter->killParticleEffect(); emitter = 0; } + + if (!enqueuedForDelete) + { + enqueuedForDelete = true; + deleteShots.push_back(this); + } } void Shot::doHitEffects() @@ -778,7 +784,7 @@ bool Shot::isObstructed(float dt) const void Shot::onUpdate(float dt) { if (dsq->game->isPaused()) return; - if (dsq->continuity.getWorldType() != WT_NORMAL) return; + if (dsq->game->isWorldPaused()) return; if (!shotData) return; diff --git a/Aquaria/Shot.h b/Aquaria/Shot.h index 657a55c..3864dd2 100644 --- a/Aquaria/Shot.h +++ b/Aquaria/Shot.h @@ -128,7 +128,6 @@ public: protected: float waveTimer; - bool fired; void suicide(); @@ -141,6 +140,8 @@ protected: void onEndOfLife(); bool dead; + bool fired; + bool enqueuedForDelete; void onUpdate(float dt); private: diff --git a/Aquaria/SteamRender.cpp b/Aquaria/SteamRender.cpp index a6a5281..6502670 100644 --- a/Aquaria/SteamRender.cpp +++ b/Aquaria/SteamRender.cpp @@ -41,7 +41,7 @@ void SteamRender::onUpdate(float dt) void SteamRender::onRender() { #ifdef BBGE_BUILD_OPENGL - glDisable(GL_CULL_FACE); + //glDisable(GL_CULL_FACE); //int qs = 0; for (Path *p = dsq->game->getFirstPathOfType(PATH_STEAM); p; p = p->nextOfType) @@ -121,7 +121,7 @@ void SteamRender::onRender() } } - glEnable(GL_CULL_FACE); + //glEnable(GL_CULL_FACE); #endif } diff --git a/Aquaria/StringBank.cpp b/Aquaria/StringBank.cpp index d1d144f..abdbb8d 100644 --- a/Aquaria/StringBank.cpp +++ b/Aquaria/StringBank.cpp @@ -41,6 +41,9 @@ void StringBank::load() fname = localisePath(dsq->mod.getPath() + "stringbank.txt", dsq->mod.getPath()); _load(fname); } + + if(stringMap.empty()) + exit_error("Failed to load data/stringbank.txt"); } void StringBank::_load(const std::string &file) diff --git a/Aquaria/UserSettings.cpp b/Aquaria/UserSettings.cpp index 49e19f4..32d47e9 100644 --- a/Aquaria/UserSettings.cpp +++ b/Aquaria/UserSettings.cpp @@ -91,12 +91,6 @@ void UserSettings::save() TiXmlElement xml_video("Video"); { - TiXmlElement xml_shader("Shader"); - { - xml_shader.SetAttribute("num", video.shader); - } - xml_video.InsertEndChild(xml_shader); - TiXmlElement xml_blur("Blur"); { xml_blur.SetAttribute("on", video.blur); @@ -413,8 +407,6 @@ void UserSettings::load(bool doApply, const std::string &overrideFile) TiXmlElement *xml_video = doc.FirstChildElement("Video"); if (xml_video) { - readInt(xml_video, "Shader", "num", &video.shader); - readInt(xml_video, "Blur", "on", &video.blur); readInt(xml_video, "NoteEffects", "on", &video.noteEffects); diff --git a/Aquaria/UserSettings.h b/Aquaria/UserSettings.h index 1e31763..1c4607e 100644 --- a/Aquaria/UserSettings.h +++ b/Aquaria/UserSettings.h @@ -100,7 +100,6 @@ public: numParticles = 2048; parallaxOn0 = parallaxOn1 = parallaxOn2 = 1; saveSlotScreens = 1; - shader = 0; blur = 1; noteEffects = 0; fpsSmoothing = 30; @@ -115,7 +114,6 @@ public: displaylists = 0; worldMapRevealMethod = 0; } - int shader; int blur; int noteEffects; int fpsSmoothing; diff --git a/Aquaria/Web.cpp b/Aquaria/Web.cpp index 262df92..ae8c8e7 100644 --- a/Aquaria/Web.cpp +++ b/Aquaria/Web.cpp @@ -82,6 +82,14 @@ void Web::setPoint(int pt, const Vector &v) points[pt] = v; } +Vector Web::getPoint(int pt) const +{ + Vector v; + if (pt >= 0 || pt < points.size()) + v = points[pt]; + return v; +} + int Web::getNumPoints() { return points.size(); @@ -150,7 +158,7 @@ void Web::onRender() //glDisable(GL_BLEND); glLineWidth(4); - glDisable(GL_CULL_FACE); + //glDisable(GL_CULL_FACE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBegin(GL_LINES); diff --git a/Aquaria/Web.h b/Aquaria/Web.h index 78762d0..8236ac8 100644 --- a/Aquaria/Web.h +++ b/Aquaria/Web.h @@ -30,6 +30,7 @@ public: Web(); int addPoint(const Vector &point = Vector(0,0)); void setPoint(int pt, const Vector &v); + Vector getPoint(int pt) const; void setParentEntity(Entity *e); int getNumPoints(); typedef std::list Webs; diff --git a/Aquaria/WorldMapRender.cpp b/Aquaria/WorldMapRender.cpp index e9f1b9f..add5195 100644 --- a/Aquaria/WorldMapRender.cpp +++ b/Aquaria/WorldMapRender.cpp @@ -266,9 +266,9 @@ protected: q->setBlendType(BLEND_ADD); addChild(q, PM_POINTER); - std::ostringstream os; - os << "children: " << children.size(); - debugLog(os.str()); + //std::ostringstream os; + //os << "children: " << children.size(); + //debugLog(os.str()); } else { diff --git a/BBGE/AfterEffect.cpp b/BBGE/AfterEffect.cpp index 2879cf8..938d535 100644 --- a/BBGE/AfterEffect.cpp +++ b/BBGE/AfterEffect.cpp @@ -32,9 +32,9 @@ Effect::Effect() AfterEffectManager::AfterEffectManager(int xDivs, int yDivs) { active = false; - activeShader = AS_NONE; numEffects = 0; bRenderGridPoints = true; + shaderPipeline.resize(10, 0); screenWidth = core->getWindowWidth(); screenHeight = core->getWindowHeight(); @@ -43,46 +43,11 @@ AfterEffectManager::AfterEffectManager(int xDivs, int yDivs) this->yDivs = 0; drawGrid = 0; - -#ifdef BBGE_BUILD_OPENGL - this->xDivs = xDivs; this->yDivs = yDivs; - //cameraPointer = nCameraPointer; - //Asssuming the resolutions values are > 256 and < 2048 - //Set the texture heights and widths - if (core->frameBuffer.isInited()) - { - textureWidth = core->frameBuffer.getWidth(); - textureHeight = core->frameBuffer.getHeight(); - } - else - { - if (screenWidth <= 512) - textureWidth = 512; - else if (screenWidth <= 1024) - textureWidth = 1024; - else - textureWidth = 2048; - if (screenHeight <= 512) - textureHeight = 512; - else if (screenHeight <= 1024) - textureHeight = 1024; - else - textureHeight = 2048; - } - - //create our texture - glGenTextures(1,&texture); - glBindTexture(GL_TEXTURE_2D,texture); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, 3, textureWidth, textureHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); - -#endif - //BuildMip(); + reloadDevice(); if (xDivs != 0 && yDivs != 0) { @@ -98,14 +63,9 @@ AfterEffectManager::AfterEffectManager(int xDivs, int yDivs) void AfterEffectManager::loadShaders() { - /* - blurShader.load("data/shaders/stan.vert", "data/shaders/blur.frag"); - bwShader.load("data/shaders/stan.vert", "data/shaders/bw.frag"); - washoutShader.load("data/shaders/stan.vert", "data/shaders/washout.frag"); - //motionBlurShader.load("data/shaders/stan.vert", "data/shaders/hoblur.frag"); - motionBlurShader.load("data/shaders/stan.vert", "data/shaders/blur.frag"); - glowShader.load("data/shaders/stan.vert", "data/shaders/glow.frag"); - */ + deleteShaders(); + + // ...Load shaders here... } AfterEffectManager::~AfterEffectManager() @@ -120,6 +80,7 @@ AfterEffectManager::~AfterEffectManager() delete[] drawGrid; } deleteEffects(); + deleteShaders(); } void AfterEffectManager::deleteEffects() @@ -137,6 +98,21 @@ void AfterEffectManager::deleteEffects() openSpots.pop(); } +void AfterEffectManager::deleteShaders() +{ + for(size_t i = 0; i < shaderPipeline.size(); ++i) + shaderPipeline[i] = 0; + + for(size_t i = 0; i < loadedShaders.size(); ++i) + { + if(loadedShaders[i]) + { + delete loadedShaders[i]; + loadedShaders[i] = 0; + } + } +} + void AfterEffectManager::clear() { deleteEffects(); @@ -190,49 +166,20 @@ void AfterEffectManager::destroyEffect(int id) openSpots.push(id); } -void AfterEffectManager::capture() -{ - /* -#ifdef BBGE_BUILD_OPENGL - glBindTexture(GL_TEXTURE_2D,texture); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, screenWidth, screenHeight); -#endif - */ - if (core->frameBuffer.isInited()) - { - core->frameBuffer.endCapture(); - //core->enable2D(core->pixelScale); - } - else - { -#ifdef BBGE_BUILD_OPENGL - glBindTexture(GL_TEXTURE_2D,texture); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, screenWidth, screenHeight); -#endif - } -//glDisable(GL_TEXTURE_2D); - -} void AfterEffectManager::render() { + assert(core->frameBuffer.isInited()); + #ifdef BBGE_BUILD_OPENGL glPushMatrix(); - //glDisable(GL_BLEND); - //glEnable(GL_BLEND); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glDisable (GL_ALPHA_TEST); glDisable(GL_BLEND); - capture(); + core->frameBuffer.endCapture(); glTranslatef(core->cameraPos.x, core->cameraPos.y, 0); glScalef(core->invGlobalScale, core->invGlobalScale,0); - /* - static float angle; - angle += 0.03f; - */ - //glRotatef(angle, 0, 0, 1); - //glColor4f(1,1,1,0.75); + glColor4f(1,1,1,1); renderGrid(); //renderGridPoints(); @@ -240,86 +187,49 @@ void AfterEffectManager::render() #endif } -void AfterEffectManager::setActiveShader(ActiveShader as) -{ - activeShader = as; -} - void AfterEffectManager::renderGrid() { #ifdef BBGE_BUILD_OPENGL - //glBindTexture(GL_TEXTURE_2D, texture); - if (core->frameBuffer.isInited()) - core->frameBuffer.bindTexture(); - else - glBindTexture(GL_TEXTURE_2D, texture); - - - //bwShader.bind(); - Shader *activeShader=0; - if (core->frameBuffer.isInited()) + int firstShader = -1; + int lastShader = -1; + Shader *activeShader = 0; + for (size_t i = 0; i < shaderPipeline.size(); ++i) { - switch(this->activeShader) + if(shaderPipeline[i]) { - case AS_BLUR: - activeShader = &blurShader; - break; - case AS_BW: - activeShader = &bwShader; - break; - case AS_WASHOUT: - activeShader = &washoutShader; - break; - case AS_MOTIONBLUR: - activeShader = &motionBlurShader; - break; - case AS_GLOW: - activeShader = &glowShader; - break; + if(firstShader < 0) + { + firstShader = i; + activeShader = shaderPipeline[i]; + } + lastShader = i; } } - if (activeShader) - activeShader->bind(); - screenWidth = core->getWindowWidth(); screenHeight = core->getWindowHeight(); - /* - float percentX, percentY; - percentX = 1; - percentY = 0.5; - */ - - /* - percentX = (float)textureWidth/(float)screenWidth; - percentY = (float)textureHeight/(float)screenHeight; - */ - float percentX, percentY; percentX = (float)screenWidth/(float)textureWidth; percentY = (float)screenHeight/(float)textureHeight; - - /* - if (screenWidth <= textureWidth) - { - percentX = (float)screenWidth/(float)textureWidth; - percentY = (float)screenHeight/(float)textureHeight; - } - else - { - percentY = 10; - } - */ - - int vw = core->getVirtualWidth(); int vh = core->getVirtualHeight(); int offx = -core->getVirtualOffX(); int offy = -core->getVirtualOffY(); + core->frameBuffer.bindTexture(); + + if(activeShader) + { + activeShader->bind(); + activeShader->setInt("tex", 0); + + if(firstShader != lastShader) + backupBuffer.startCapture(); + } + //float div = xDivs; for (int i = 0; i < (xDivs-1); i++) { @@ -347,6 +257,56 @@ void AfterEffectManager::renderGrid() } } + if (activeShader) + activeShader->unbind(); + + float width2 = float(vw)/2; + float height2 = float(vh)/2; + + + if(firstShader != lastShader) + { + // From here on: secondary shader passes. + // We just outputted to the backup buffer... + FrameBuffer *fbIn = &core->frameBuffer; + FrameBuffer *fbOut = &backupBuffer; + + + for(int i = firstShader + 1; i <= lastShader; ++i) + { + activeShader = shaderPipeline[i]; + if(!activeShader) + continue; + + // Swap and exchange framebuffers. The old output buffer serves as texture input for the other one + fbOut->endCapture(); + std::swap(fbIn, fbOut); + fbIn->bindTexture(); + + // If this is the last pass, do not render to a frame buffer again + if(i != lastShader) + fbOut->startCapture(); + + activeShader->bind(); + activeShader->setInt("tex", 0); + + // note that offx, offy are negative here! + glBegin(GL_QUADS); + glTexCoord2d(0.0f, 0.0f); + glVertex3f(offx, vh+offy, 0.0f); + glTexCoord2d(percentX, 0.0f); + glVertex3f( vw+offx, vh+offy, 0.0f); + glTexCoord2d(percentX, percentY); + glVertex3f( vw+offx, offy, 0.0f); + glTexCoord2d(0.0f, percentY); + glVertex3f(offx, offy, 0.0f); + glEnd(); + + activeShader->unbind(); + } + } + + // uncomment to render grid points /* glBindTexture(GL_TEXTURE_2D, 0); @@ -382,9 +342,6 @@ void AfterEffectManager::renderGrid() //glDisable(GL_TEXTURE_2D); RenderObject::lastTextureApplied = 0; glBindTexture(GL_TEXTURE_2D, 0); - - if (activeShader) - activeShader->unbind(); //bwShader.unbind(); //glActiveTextureARB(GL_TEXTURE0_ARB); @@ -415,8 +372,8 @@ void AfterEffectManager::renderGridPoints() void AfterEffectManager::unloadDevice() { - if (texture) - glDeleteTextures(1,&texture); + backupBuffer.unloadDevice(); + deleteShaders(); } void AfterEffectManager::reloadDevice() @@ -431,22 +388,18 @@ void AfterEffectManager::reloadDevice() } else { - if (screenWidth <= 1024) - textureWidth = 1024; - else - textureWidth = 2048; - if (screenHeight <= 1024) - textureHeight = 1024; - else - textureHeight = 2048; + textureWidth = screenWidth; + sizePowerOf2Texture(textureWidth); + textureHeight = screenHeight; + sizePowerOf2Texture(textureHeight); } - //create our texture - glGenTextures(1,&texture); - glBindTexture(GL_TEXTURE_2D,texture); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, 3, textureWidth, textureHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + if(backupBuffer.isInited()) + backupBuffer.reloadDevice(); + else + backupBuffer.init(-1, -1, true); + + loadShaders(); } void AfterEffectManager::addEffect(Effect *e) @@ -598,3 +551,79 @@ void RippleEffect::update(float dt, Vector ** drawGrid, int xDivs, int yDivs) } } } + +int AfterEffectManager::loadShaderFile(const char *vert, const char *frag) +{ + Shader *sh = new Shader(); + sh->load(vert, frag); + if(!sh->isLoaded()) + { + delete sh; + return 0; + } + return _insertShader(sh); +} + +int AfterEffectManager::loadShaderSrc(const char *vert, const char *frag) +{ + Shader *sh = new Shader(); + sh->loadSrc(vert, frag); + if(!sh->isLoaded()) + { + delete sh; + return 0; + } + return _insertShader(sh); +} + +Shader *AfterEffectManager::getShaderPtr(int handle) +{ + size_t idx = handle - 1; + return idx < loadedShaders.size() ? loadedShaders[idx] : 0; +} + +void AfterEffectManager::setShaderPipelineSize(size_t size) +{ + shaderPipeline.resize(size, 0); +} + +bool AfterEffectManager::setShaderPipelinePos(int handle, size_t pos) +{ + if(pos < shaderPipeline.size()) + { + shaderPipeline[pos] = getShaderPtr(handle); + return true; + } + return false; +} + +// returns handle (= index + 1) +int AfterEffectManager::_insertShader(Shader *sh) +{ + for(size_t i = 0; i < loadedShaders.size(); ++i) + { + if(!loadedShaders[i]) + { + loadedShaders[i] = sh; + return i+1; + } + } + loadedShaders.push_back(sh); + return loadedShaders.size(); +} + +void AfterEffectManager::unloadShader(int handle) +{ + Shader *sh = getShaderPtr(handle); + if(!sh) + return; + + for(size_t i = 0; i < shaderPipeline.size(); ++i) + if(shaderPipeline[i] == sh) + shaderPipeline[i] = 0; + + size_t idx = handle - 1; + loadedShaders[idx] = 0; + delete sh; +} + diff --git a/BBGE/AfterEffect.h b/BBGE/AfterEffect.h index fd755d3..90c7d9f 100644 --- a/BBGE/AfterEffect.h +++ b/BBGE/AfterEffect.h @@ -72,16 +72,6 @@ public: float time; }; -enum ActiveShader -{ - AS_NONE = 0, - AS_BLUR , - AS_BW , - AS_WASHOUT , - AS_MOTIONBLUR , - AS_GLOW -}; - class AfterEffectManager { public: @@ -96,12 +86,12 @@ public: void resetGrid(); - void capture(); void render(); void renderGrid(); void renderGridPoints(); void loadShaders(); + void deleteShaders(); void unloadDevice(); void reloadDevice(); @@ -111,12 +101,6 @@ public: bool active; - void setActiveShader(ActiveShader as); - -#ifdef BBGE_BUILD_OPENGL - GLuint texture; -#endif - bool bRenderGridPoints; int numEffects; @@ -124,11 +108,23 @@ public: int screenWidth, screenHeight; int textureWidth, textureHeight; - Shader blurShader, bwShader, washoutShader, motionBlurShader, glowShader; + Vector ** drawGrid; - Vector ** drawGrid; + // returns handle > 0 on success + int loadShaderFile(const char *vert, const char *frag); + int loadShaderSrc(const char *vert, const char *frag); + Shader *getShaderPtr(int handle); + void setShaderPipelineSize(size_t size); + bool setShaderPipelinePos(int handle, size_t pos); + void unloadShader(int handle); + +protected: + int _insertShader(Shader *sh); + + std::vector shaderPipeline; // Shaders are applied in this order. Can contain the same pointer more than once. + std::vector loadedShaders; + FrameBuffer backupBuffer; - ActiveShader activeShader; }; diff --git a/BBGE/BBGECompileConfig.h b/BBGE/BBGECompileConfig.h index 762a1c6..125b5bf 100644 --- a/BBGE/BBGECompileConfig.h +++ b/BBGE/BBGECompileConfig.h @@ -5,7 +5,7 @@ #define BBGE_BUILD_SDL 1 #define BBGE_BUILD_FRAMEBUFFER 1 -//#define BBGE_BUILD_SHADERS 1 +#define BBGE_BUILD_SHADERS 1 #define BBGE_BUILD_OPENGL 1 #define BBGE_BUILD_OPENGL_DYNAMIC 1 #define BBGE_BUILD_FMOD_OPENAL_BRIDGE 1 diff --git a/BBGE/Base.cpp b/BBGE/Base.cpp index ebaa09c..b996122 100644 --- a/BBGE/Base.cpp +++ b/BBGE/Base.cpp @@ -291,8 +291,7 @@ bool exists(const std::string &f, bool makeFatal, bool skipVFS) if (makeFatal && !e) { - errorLog(std::string("Could not open [" + f + "]")); - exit(0); + exit_error("Could not open [" + f + "]"); } return e; @@ -301,7 +300,7 @@ bool exists(const std::string &f, bool makeFatal, bool skipVFS) void drawCircle(float radius, int stepSize) { #ifdef BBGE_BUILD_OPENGL - glDisable(GL_CULL_FACE); + //glDisable(GL_CULL_FACE); glBegin(GL_POLYGON); { @@ -312,14 +311,14 @@ void drawCircle(float radius, int stepSize) } glEnd(); - glEnable(GL_CULL_FACE); + //glEnable(GL_CULL_FACE); #endif } -void fatalError(const std::string &message) +void exit_error(const std::string &message) { - msg(message); - exit(0); + errorLog(message); + exit(1); } std::string parseCommand(const std::string &line, const std::string &command) @@ -424,8 +423,7 @@ void errorLog(const std::string &s) } else { - //msg("Core Not Initialized"); - //MessageBox(0, s.c_str(), "ErrorLog (Core Not Initalized)", MB_OK); + messageBox("Error!", s); } } @@ -775,17 +773,18 @@ std::vector getFileList(std::string path, std::string type, int par return list; } -std::string msg(const std::string &message) +void messageBox(const std::string& title, const std::string &msg) { - core->msg(message); - return message; -} - -void msgVector(const std::string &name, const Vector &vec) -{ - std::ostringstream os; - os << name << ": (" << vec.x <<", " << vec.y << ", " << vec.z << ")"; - msg (os.str()); +#ifdef BBGE_BUILD_WINDOWS + MessageBox (0,msg.c_str(),title.c_str(),MB_OK); +#elif defined(BBGE_BUILD_MACOSX) + cocoaMessageBox(title, msg); +#elif defined(BBGE_BUILD_UNIX) + // !!! FIXME: probably don't want the whole GTK+ dependency in here... + fprintf(stderr, "%s: %s\n", title.c_str(), msg.c_str()); +#else +#error Please define your platform. +#endif } Vector getNearestPointOnLine(Vector a, Vector b, Vector c) diff --git a/BBGE/Base.h b/BBGE/Base.h index 586a944..9c34277 100644 --- a/BBGE/Base.h +++ b/BBGE/Base.h @@ -257,11 +257,9 @@ bool isVectorInRect(const Vector &vec, const Vector &coord1, const Vector &coord std::string parseCommand(const std::string &line, const std::string &command); -std::string msg(const std::string &message); +void messageBox(const std::string &title, const std::string& msg); -void msgVector(const std::string &name, const Vector &vec); - -void fatalError(const std::string &message); +void exit_error(const std::string &message); unsigned hash(const std::string &string); diff --git a/BBGE/BitmapFont.cpp b/BBGE/BitmapFont.cpp index dca022e..9bf0fc2 100644 --- a/BBGE/BitmapFont.cpp +++ b/BBGE/BitmapFont.cpp @@ -317,7 +317,7 @@ void BitmapText::onRender() glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); */ - glDisable(GL_CULL_FACE); + //glDisable(GL_CULL_FACE); //glScalef(1, -1, 0); @@ -374,7 +374,7 @@ void BitmapText::onRender() } } - glEnable(GL_CULL_FACE); + //glEnable(GL_CULL_FACE); glBindTexture(GL_TEXTURE_2D, 0); #endif diff --git a/BBGE/Core.cpp b/BBGE/Core.cpp index ac767ce..c659d2e 100644 --- a/BBGE/Core.cpp +++ b/BBGE/Core.cpp @@ -818,7 +818,7 @@ bool Core::getMetaState() void Core::errorLog(const std::string &s) { - messageBox("Message", s); + messageBox("Error!", s); debugLog(s); } @@ -828,16 +828,7 @@ void cocoaMessageBox(const std::string &title, const std::string &msg); void Core::messageBox(const std::string &title, const std::string &msg) { -#ifdef BBGE_BUILD_WINDOWS - MessageBox (0,msg.c_str(),title.c_str(),MB_OK); -#elif defined(BBGE_BUILD_MACOSX) - cocoaMessageBox(title, msg); -#elif defined(BBGE_BUILD_UNIX) - // !!! FIXME: probably don't want the whole GTK+ dependency in here... - fprintf(stderr, "%s: %s\n", title.c_str(), msg.c_str()); -#else -#error Please define your platform. -#endif + ::messageBox(title, msg); } void Core::debugLog(const std::string &s) @@ -1276,7 +1267,7 @@ void Core::init() if((SDL_Init(0))==-1) { - exit(0); + exit_error("Failed to init SDL"); } #endif @@ -1849,11 +1840,13 @@ void Core::setSDLGLAttributes() #define GLAPIENTRY #endif +unsigned int Core::dbg_numRenderCalls = 0; + #ifdef BBGE_BUILD_OPENGL_DYNAMIC #define GL_FUNC(ret,fn,params,call,rt) \ extern "C" { \ static ret (GLAPIENTRY *p##fn) params = NULL; \ - ret GLAPIENTRY fn params { rt p##fn call; } \ + ret GLAPIENTRY fn params { ++Core::dbg_numRenderCalls; rt p##fn call; } \ } #include "OpenGLStubs.h" #undef GL_FUNC @@ -1917,16 +1910,15 @@ bool Core::initGraphicsLibrary(int width, int height, bool fullscreen, int vsync { if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) { - errorLog(std::string("SDL Error: ") + std::string(SDL_GetError())); - exit(0); + exit_error(std::string("SDL Error: ") + std::string(SDL_GetError())); } #if BBGE_BUILD_OPENGL_DYNAMIC if (SDL_GL_LoadLibrary(NULL) == -1) { - errorLog(std::string("SDL_GL_LoadLibrary Error: ") + std::string(SDL_GetError())); + std::string err = std::string("SDL_GL_LoadLibrary Error: ") + std::string(SDL_GetError()); SDL_Quit(); - exit(0); + exit_error(err); } #endif } @@ -1950,9 +1942,8 @@ bool Core::initGraphicsLibrary(int width, int height, bool fullscreen, int vsync { std::ostringstream os; os << "Couldn't set resolution [" << width << "x" << height << "]\n" << SDL_GetError(); - errorLog(os.str()); SDL_Quit(); - exit(0); + exit_error(os.str()); } #if BBGE_BUILD_OPENGL_DYNAMIC @@ -1960,9 +1951,8 @@ bool Core::initGraphicsLibrary(int width, int height, bool fullscreen, int vsync { std::ostringstream os; os << "Couldn't load OpenGL symbols we need\n"; - errorLog(os.str()); SDL_Quit(); - exit(0); + exit_error(os.str()); } #endif } @@ -2632,13 +2622,6 @@ void Core::setDockIcon(const std::string &ident) { } -void Core::msg(const std::string &message) -{ -#ifdef BBGE_BUILD_WINDOWS - MessageBox(0, message.c_str(), "Message", MB_OK); -#endif -} - void Core::setMousePosition(const Vector &p) { Vector lp = core->mouse.position; @@ -3015,6 +2998,8 @@ void Core::main(float runTime) updateCullData(); + dbg_numRenderCalls = 0; + if (settings.renderOn) { if (verbose) debugLog("dark layer prerender"); @@ -3857,10 +3842,6 @@ void Core::render(int startLayer, int endLayer, bool useFrameBufferIfAvail) int i = renderObjectLayerOrder[c]; if (i == -1) continue; if ((startLayer != -1 && endLayer != -1) && (i < startLayer || i > endLayer)) continue; - if (afterEffectManager && afterEffectManager->active && i == afterEffectManagerLayer) - { - afterEffectManager->render(); - } if (i == postProcessingFx.layer) { @@ -3890,6 +3871,11 @@ void Core::render(int startLayer, int endLayer, bool useFrameBufferIfAvail) } } + if (afterEffectManager && afterEffectManager->active && i == afterEffectManagerLayer) + { + afterEffectManager->render(); + } + RenderObjectLayer *r = &renderObjectLayers[i]; RenderObject::rlayer = r; if (r->visible) @@ -4844,14 +4830,13 @@ void Core::setupFileAccess() debugLog("Init VFS..."); if(!ttvfs::checkCompat()) - exit(1); + exit_error("ttvfs not compatible"); vfs.AddArchiveLoader(new ttvfs::VFSZipArchiveLoader); if(!vfs.LoadFileSysRoot(false)) { - errorLog("Failed to setup file access"); - exit(1); + exit_error("Failed to setup file access"); } vfs.Prepare(); diff --git a/BBGE/Core.h b/BBGE/Core.h index d0b0f0b..fbdc4ed 100644 --- a/BBGE/Core.h +++ b/BBGE/Core.h @@ -1175,8 +1175,6 @@ public: void saveSizedScreenshotTGA(const std::string &filename, int sz, int crop34); void saveCenteredScreenshotTGA(const std::string &filename, int sz); - virtual void msg(const std::string &message); - bool minimized; std::string getEnqueuedJumpState(); int cullRadius; @@ -1310,6 +1308,7 @@ public: int zgaSave(const char *filename, short int width, short int height, unsigned char pixelDepth, unsigned char *imageData); volatile int dbg_numThreadDecoders; + static unsigned int dbg_numRenderCalls; protected: diff --git a/BBGE/Emitter.cpp b/BBGE/Emitter.cpp index d92a57a..31c693e 100644 --- a/BBGE/Emitter.cpp +++ b/BBGE/Emitter.cpp @@ -306,7 +306,7 @@ void Emitter::onRender() if (data.flipH || (data.copyParentFlip && (pe->isfh() || (pe->getParent() && pe->getParent()->isfh())))) { - glDisable(GL_CULL_FACE); + //glDisable(GL_CULL_FACE); glRotatef(180, 0, 1, 0); } diff --git a/BBGE/Precacher.cpp b/BBGE/Precacher.cpp index 24e1585..3d604b8 100644 --- a/BBGE/Precacher.cpp +++ b/BBGE/Precacher.cpp @@ -34,6 +34,11 @@ Precacher::~Precacher() errorLog ("Precacher shutdown unclean"); } +void Precacher::setBaseDir(const std::string& dir) +{ + basedirOverride = dir; +} + void Precacher::clean() { for (unsigned int i = 0; i < renderObjects.size(); i++) @@ -88,6 +93,8 @@ void Precacher::precacheTex(const std::string &tex) } if (tex.empty()) return; + std::string basedir = basedirOverride.empty() ? core->getBaseTextureDirectory() : basedirOverride; + if (core->debugLogTextures) debugLog("PRECACHING: " + tex); @@ -99,7 +106,7 @@ void Precacher::precacheTex(const std::string &tex) int loc = tex.find('*'); std::string path = tex.substr(0, loc); std::string type = tex.substr(loc+1, tex.size()); - path = core->getBaseTextureDirectory() + path; + path = basedir + path; forEachFile(path, type, precacherCallback, (intptr_t)this); return; } @@ -108,9 +115,9 @@ void Precacher::precacheTex(const std::string &tex) if (loadProgressCallback) loadProgressCallback(); std::string t = tex; - if (tex.find(core->getBaseTextureDirectory()) != std::string::npos) + if (tex.find(basedir) != std::string::npos) { - t = tex.substr(core->getBaseTextureDirectory().size(), tex.size()); + t = tex.substr(basedir.size(), tex.size()); } Quad *q = new Quad; q->setTexture(t); diff --git a/BBGE/Precacher.h b/BBGE/Precacher.h index 87e9a05..4893123 100644 --- a/BBGE/Precacher.h +++ b/BBGE/Precacher.h @@ -32,11 +32,13 @@ public: void precacheList(const std::string &list, void progressCallback() = NULL); void clean(); void loadTextureRange(const std::string &file, const std::string &type, int start, int end); + void setBaseDir(const std::string& dir); std::vector renderObjects; private: bool cleaned; void (*loadProgressCallback)(); + std::string basedirOverride; }; #endif diff --git a/BBGE/Quad.cpp b/BBGE/Quad.cpp index 5fa50ee..fdcfa38 100644 --- a/BBGE/Quad.cpp +++ b/BBGE/Quad.cpp @@ -499,7 +499,7 @@ void Quad::onRender() if (!strip.empty()) { //glDisable(GL_BLEND);gggg - glDisable(GL_CULL_FACE); + //glDisable(GL_CULL_FACE); const float texBits = 1.0f / (strip.size()-1); @@ -517,7 +517,7 @@ void Quad::onRender() } glEnd(); - glEnable(GL_CULL_FACE); + //glEnable(GL_CULL_FACE); glBindTexture( GL_TEXTURE_2D, 0 ); glColor4f(1,0,0,1); glPointSize(64); @@ -802,6 +802,7 @@ void Quad::onSetTexture() PauseQuad::PauseQuad() : Quad(), pauseLevel(0) { + addType(SCO_PAUSEQUAD); } void PauseQuad::onUpdate(float dt) diff --git a/BBGE/QuadTrail.cpp b/BBGE/QuadTrail.cpp index 3a2ecd8..a299b4e 100644 --- a/BBGE/QuadTrail.cpp +++ b/BBGE/QuadTrail.cpp @@ -59,7 +59,7 @@ void QuadTrail::onRender() if (numPoints < 2) return; #ifdef BBGE_BUILD_OPENGL - glDisable(GL_CULL_FACE); + //glDisable(GL_CULL_FACE); int c = 0; Vector p, diff, dl, dr; Vector lastPoint; diff --git a/BBGE/RenderObject.cpp b/BBGE/RenderObject.cpp index 032c4c8..69b5e6d 100644 --- a/BBGE/RenderObject.cpp +++ b/BBGE/RenderObject.cpp @@ -629,7 +629,7 @@ void RenderObject::renderCall() glTranslatef(position.x, position.y, position.z); if (isfh()) { - glDisable(GL_CULL_FACE); + //glDisable(GL_CULL_FACE); glRotatef(180, 0, 1, 0); } @@ -655,7 +655,7 @@ void RenderObject::renderCall() glTranslatef(pos.x, pos.y, pos.z); if (isfh()) { - glDisable(GL_CULL_FACE); + //glDisable(GL_CULL_FACE); glRotatef(180, 0, 1, 0); } glRotatef(rotation.z+rotationOffset.z, 0, 0, 1); @@ -714,7 +714,7 @@ void RenderObject::renderCall() glRotatef(rotation.z+rotationOffset.z, 0, 0, 1); if (isfh()) { - glDisable(GL_CULL_FACE); + //glDisable(GL_CULL_FACE); glRotatef(180, 0, 1, 0); } #endif diff --git a/BBGE/RoundedRect.cpp b/BBGE/RoundedRect.cpp index 1657159..4eb86dc 100644 --- a/BBGE/RoundedRect.cpp +++ b/BBGE/RoundedRect.cpp @@ -105,7 +105,7 @@ void RoundedRect::onRender() //glBindTexture(GL_TEXTURE_2D, 0); int w2 = width/2; int h2 = height/2; - glDisable(GL_CULL_FACE); + //glDisable(GL_CULL_FACE); float iter = 0.1f; glBegin(GL_QUADS); @@ -167,7 +167,7 @@ void RoundedRect::onRender() glEnd(); - glEnable(GL_CULL_FACE); + //glEnable(GL_CULL_FACE); } void RoundedRect::show() diff --git a/BBGE/ScriptObject.cpp b/BBGE/ScriptObject.cpp index 452edbe..60b5d01 100644 --- a/BBGE/ScriptObject.cpp +++ b/BBGE/ScriptObject.cpp @@ -37,6 +37,8 @@ static const char *scriptObjTypeNames[] = /* (1 << 9) */ "Path/Node", /* (1 <<10) */ "Quad", /* (1 <<11) */ "Text", + /* (1 <<12) */ "PauseQuad", + /* (1 <<13) */ "Shader", NULL }; diff --git a/BBGE/ScriptObject.h b/BBGE/ScriptObject.h index 08cd693..a6bbb0a 100644 --- a/BBGE/ScriptObject.h +++ b/BBGE/ScriptObject.h @@ -39,6 +39,8 @@ enum ScriptObjectType SCO_PATH = 0x0200, SCO_QUAD = 0x0400, SCO_TEXT = 0x0800, + SCO_PAUSEQUAD = 0x1000, + SCO_SHADER = 0x2000, SCO_FORCE_32BIT = 0xFFFFFFFF }; diff --git a/BBGE/Shader.cpp b/BBGE/Shader.cpp index 65ca1c1..c6468bc 100644 --- a/BBGE/Shader.cpp +++ b/BBGE/Shader.cpp @@ -18,10 +18,9 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + #include "Shader.h" -#ifdef BBGE_BUILD_WINDOWS - #include -#endif +#include "algorithmx.h" #ifdef BBGE_BUILD_SHADERS // GL_ARB_shader_objects @@ -36,8 +35,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. PFNGLGETINFOLOGARBPROC glGetInfoLogARB = NULL; PFNGLLINKPROGRAMARBPROC glLinkProgramARB = NULL; PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB = NULL; - PFNGLUNIFORM4FARBPROC glUniform4fARB = NULL; - PFNGLUNIFORM1IARBPROC glUniform1iARB = NULL; + PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB = NULL; + PFNGLUNIFORM1FVARBPROC glUniform1fvARB = NULL; + PFNGLUNIFORM2FVARBPROC glUniform2fvARB = NULL; + PFNGLUNIFORM3FVARBPROC glUniform3fvARB = NULL; + PFNGLUNIFORM4FVARBPROC glUniform4fvARB = NULL; + PFNGLUNIFORM1IVARBPROC glUniform1ivARB = NULL; + PFNGLUNIFORM2IVARBPROC glUniform2ivARB = NULL; + PFNGLUNIFORM3IVARBPROC glUniform3ivARB = NULL; + PFNGLUNIFORM4IVARBPROC glUniform4ivARB = NULL; + #endif bool Shader::_wasInited = false; @@ -73,22 +80,6 @@ void Shader::staticInit() } else { -#ifdef BBGE_BUILD_GLFW - glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)glfwGetProcAddress("glCreateProgramObjectARB"); - glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)glfwGetProcAddress("glDeleteObjectARB"); - glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)glfwGetProcAddress("glUseProgramObjectARB"); - glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)glfwGetProcAddress("glCreateShaderObjectARB"); - glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)glfwGetProcAddress("glShaderSourceARB"); - glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)glfwGetProcAddress("glCompileShaderARB"); - glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)glfwGetProcAddress("glGetObjectParameterivARB"); - glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)glfwGetProcAddress("glAttachObjectARB"); - glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)glfwGetProcAddress("glGetInfoLogARB"); - glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)glfwGetProcAddress("glLinkProgramARB"); - glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)glfwGetProcAddress("glGetUniformLocationARB"); - glUniform4fARB = (PFNGLUNIFORM4FARBPROC)glfwGetProcAddress("glUniform4fARB"); - glUniform1iARB = (PFNGLUNIFORM1IARBPROC)glfwGetProcAddress("glUniform1iARB"); -#endif - #ifdef BBGE_BUILD_SDL glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glCreateProgramObjectARB"); glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)SDL_GL_GetProcAddress("glDeleteObjectARB"); @@ -101,15 +92,23 @@ void Shader::staticInit() glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)SDL_GL_GetProcAddress("glGetInfoLogARB"); glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)SDL_GL_GetProcAddress("glLinkProgramARB"); glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)SDL_GL_GetProcAddress("glGetUniformLocationARB"); - glUniform4fARB = (PFNGLUNIFORM4FARBPROC)SDL_GL_GetProcAddress("glUniform4fARB"); - glUniform1iARB = (PFNGLUNIFORM1IARBPROC)SDL_GL_GetProcAddress("glUniform1iARB"); + glGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC)SDL_GL_GetProcAddress("glGetActiveUniformARB"); + glUniform1fvARB = (PFNGLUNIFORM1FVARBPROC)SDL_GL_GetProcAddress("glUniform1fvARB"); + glUniform2fvARB = (PFNGLUNIFORM2FVARBPROC)SDL_GL_GetProcAddress("glUniform2fvARB"); + glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC)SDL_GL_GetProcAddress("glUniform3fvARB"); + glUniform4fvARB = (PFNGLUNIFORM4FVARBPROC)SDL_GL_GetProcAddress("glUniform4fvARB"); + glUniform1ivARB = (PFNGLUNIFORM1IVARBPROC)SDL_GL_GetProcAddress("glUniform1ivARB"); + glUniform2ivARB = (PFNGLUNIFORM2IVARBPROC)SDL_GL_GetProcAddress("glUniform2ivARB"); + glUniform3ivARB = (PFNGLUNIFORM3IVARBPROC)SDL_GL_GetProcAddress("glUniform3ivARB"); + glUniform4ivARB = (PFNGLUNIFORM4IVARBPROC)SDL_GL_GetProcAddress("glUniform4ivARB"); #endif if( !glCreateProgramObjectARB || !glDeleteObjectARB || !glUseProgramObjectARB || !glCreateShaderObjectARB || !glCreateShaderObjectARB || !glCompileShaderARB || !glGetObjectParameterivARB || !glAttachObjectARB || !glGetInfoLogARB || - !glLinkProgramARB || !glGetUniformLocationARB || !glUniform4fARB || - !glUniform1iARB ) + !glLinkProgramARB || !glGetUniformLocationARB || !glGetActiveUniformARB || + !glUniform1fvARB || !glUniform2fvARB || !glUniform3fvARB || !glUniform4fvARB || + !glUniform1ivARB || !glUniform2ivARB || !glUniform3ivARB || !glUniform4ivARB) { glCreateProgramObjectARB = 0; debugLog("One or more GL_ARB_shader_objects functions were not found"); @@ -132,88 +131,35 @@ end: Shader::Shader() { - loaded = false; - mode = 0; + numUniforms = -1; + uniformsDirty = false; + #ifdef BBGE_BUILD_OPENGL - g_vertexShader = 0; - g_fragmentShader = 0; g_programObj = 0; - vx = vy = vz = vw = 0; - g_location_texture = 0; - g_location_mode = 0; - g_location_value = 0; #endif } Shader::~Shader() +{ + unload(); +} + +void Shader::unload() { #ifdef BBGE_BUILD_SHADERS if (!_useShaders) return; - if (g_vertexShader) - glDeleteObjectARB( g_vertexShader ); - if (g_fragmentShader) - glDeleteObjectARB( g_fragmentShader ); if (g_programObj) + { glDeleteObjectARB( g_programObj ); + g_programObj = 0; + } #endif } -bool Shader::isLoaded() +bool Shader::isLoaded() const { - return loaded; -} - -void Shader::setMode(int mode) -{ - this->mode = mode; -} - -void Shader::setValue(float x, float y, float z, float w) -{ - vx = x; - vy = y; - vz = z; - vw = w; -} - -unsigned char *readShaderFile( const char *fileName ) -{ - debugLog("readShaderFile()"); -#ifdef BBGE_BUILD_WINDOWS - FILE *file = fopen( fileName, "r" ); // FIXME: should this code ever be re-activated, adjust to VFS! -- fg - - if( file == NULL ) - { - errorLog("Cannot open shader file!"); - return 0; - } - - struct _stat fileStats; - - if( _stat( fileName, &fileStats ) != 0 ) - { - errorLog("Cannot get file stats for shader file!"); - return 0; - } - - - unsigned char *buffer = new unsigned char[fileStats.st_size]; - - int bytes = fread( buffer, 1, fileStats.st_size, file ); - - buffer[bytes] = 0; - - fclose( file ); - - debugLog("End readShaderFile()"); - - return buffer; - -#else - debugLog("End readShaderFile()"); - return 0; -#endif + return g_programObj != 0; } void Shader::reload() @@ -226,13 +172,8 @@ void Shader::bind() #ifdef BBGE_BUILD_SHADERS if (!_useShaders) return; - glUseProgramObjectARB( g_programObj ); - if( g_location_texture != -1 ) - glUniform1iARB( g_location_texture, 0 ); - if ( g_location_mode ) - glUniform1iARB( g_location_mode, mode); - if ( g_location_value ) - glUniform4fARB( g_location_value, vx, vy, vz, vw); + glUseProgramObjectARB(g_programObj); + _flushUniforms(); #endif } @@ -241,142 +182,273 @@ void Shader::unbind() #ifdef BBGE_BUILD_SHADERS if (!_useShaders) return; - glUseProgramObjectARB( NULL ); + glUseProgramObjectARB(0); #endif } +unsigned int Shader::_compileShader(int type, const char *src, char *errbuf, size_t errbufsize) +{ +#ifdef BBGE_BUILD_SHADERS + GLint compiled = 0; + GLhandleARB handle = glCreateShaderObjectARB(type); + if(!handle) + { + std::ostringstream os; + os << "Failed to create shader object of type " << type; + debugLog(os.str()); + return 0; + } + + glShaderSourceARB( handle, 1, &src, NULL ); + glCompileShaderARB( handle); + + glGetObjectParameterivARB(handle, GL_OBJECT_COMPILE_STATUS_ARB, &compiled); + glGetInfoLogARB(handle, errbufsize, NULL, errbuf); + if(!compiled) + { + glDeleteObjectARB(handle); + handle = 0; + } + GLint err = glGetError(); + if(err != GL_NO_ERROR) + { + std::ostringstream os; + os << "Shader::_compileShader: Unexpected error " << err; + errorLog(os.str()); + } + return handle; +#endif + return 0; +} + void Shader::load(const std::string &file, const std::string &fragFile) { staticInit(); - loaded = false; - -#ifdef BBGE_BUILD_SHADERS if(!_useShaders) return; debugLog("Shader::load("+file+", "+fragFile+")"); - g_location_texture = 0; - g_location_mode = 0; - g_location_value = 0; - - debugLog("Shader::load 1"); this->vertFile = file; this->fragFile = fragFile; - // - // If the required extension is present, get the addresses of its - // functions that we wish to use... - // - const char *vertexShaderStrings[1]; - const char *fragmentShaderStrings[1]; - GLint bVertCompiled; - GLint bFragCompiled; - GLint bLinked; + char *vertCode = file.length() ? readFile(file) : NULL; + char *fragCode = fragFile.length() ? readFile(fragFile) : NULL; + + loadSrc(vertCode, fragCode); + + delete [] vertCode; + delete [] fragCode; +} + +void Shader::loadSrc(const char *vertCode, const char *fragCode) +{ + staticInit(); + unload(); + + if(!_useShaders) + return; + +#ifdef BBGE_BUILD_SHADERS + char str[4096]; + GLhandleARB vertexShader = 0; + GLhandleARB fragmentShader = 0; + // // Create the vertex shader... // - - debugLog("Shader::load 2"); - - g_vertexShader = glCreateShaderObjectARB( GL_VERTEX_SHADER_ARB ); - - unsigned char *vertexShaderAssembly = readShaderFile( file.c_str() ); - vertexShaderStrings[0] = (char*)vertexShaderAssembly; - glShaderSourceARB( g_vertexShader, 1, vertexShaderStrings, NULL ); - glCompileShaderARB( g_vertexShader); - delete[] vertexShaderAssembly; - - glGetObjectParameterivARB( g_vertexShader, GL_OBJECT_COMPILE_STATUS_ARB, - &bVertCompiled ); - if( bVertCompiled == false ) - //if (true) + if(vertCode && *vertCode && !(vertexShader = _compileShader(GL_VERTEX_SHADER_ARB, vertCode, str, sizeof(str)))) { - glGetInfoLogARB(g_vertexShader, sizeof(str), NULL, str); std::ostringstream os; - os << "Vertex Shader Compile Error: " << str; - debugLog(os.str()); + os << "Vertex Shader Compile Error [" << vertFile << "]:\n" << str; + errorLog(os.str()); return; } // // Create the fragment shader... // - - debugLog("Shader::load 3"); - - g_fragmentShader = glCreateShaderObjectARB( GL_FRAGMENT_SHADER_ARB ); - - unsigned char *fragmentShaderAssembly = readShaderFile( fragFile.c_str() ); - fragmentShaderStrings[0] = (char*)fragmentShaderAssembly; - glShaderSourceARB( g_fragmentShader, 1, fragmentShaderStrings, NULL ); - glCompileShaderARB( g_fragmentShader ); - delete[] fragmentShaderAssembly; - - glGetObjectParameterivARB( g_fragmentShader, GL_OBJECT_COMPILE_STATUS_ARB, - &bFragCompiled ); - if( bFragCompiled == false ) + if(fragCode && *fragCode && !(fragmentShader = _compileShader(GL_FRAGMENT_SHADER_ARB, fragCode, str, sizeof(str)))) { - glGetInfoLogARB( g_fragmentShader, sizeof(str), NULL, str ); std::ostringstream os; - os << "Fragment Shader Compile Error: " << str; - debugLog(os.str()); + os << "Fragment Shader Compile Error [" << fragFile << "]:\n" << str; + errorLog(os.str()); return; } - debugLog("Shader::load 4"); - // // Create a program object and attach the two compiled shaders... // - g_programObj = glCreateProgramObjectARB(); - if (!g_programObj || !g_vertexShader || !g_fragmentShader) + if (!(g_programObj && (vertexShader || fragmentShader))) { - debugLog("programObj / vertexShader / fragmentShader problem"); + errorLog("programObj / vertexShader / fragmentShader problem"); + unload(); return; } - glAttachObjectARB( g_programObj, g_vertexShader ); - glAttachObjectARB( g_programObj, g_fragmentShader ); - // // Link the program object and print out the info log... // + if(vertexShader) + glAttachObjectARB( g_programObj, vertexShader ); + if(fragmentShader) + glAttachObjectARB( g_programObj, fragmentShader ); glLinkProgramARB( g_programObj ); + + // Shader objects will be deleted as soon as the program object is deleted + if(vertexShader) + glDeleteObjectARB(vertexShader); + if(fragmentShader) + glDeleteObjectARB(fragmentShader); + + GLint bLinked; glGetObjectParameterivARB( g_programObj, GL_OBJECT_LINK_STATUS_ARB, &bLinked ); - debugLog("Shader::load 5"); - if( bLinked == false ) + if(!bLinked) { glGetInfoLogARB( g_programObj, sizeof(str), NULL, str ); std::ostringstream os; os << "Shader Linking Error: " << str; - debugLog(os.str()); + errorLog(os.str()); + unload(); return; } - // - // Locate some parameters by name so we can set them later... - // - - debugLog("Shader::load 6"); - - g_location_texture = glGetUniformLocationARB( g_programObj, "tex" ); - g_location_mode = glGetUniformLocationARB( g_programObj, "mode" ); - g_location_value = glGetUniformLocationARB( g_programObj, "value" ); - - debugLog("Shader::load 7"); - - loaded = true; + _queryUniforms(); #endif - debugLog("End Shader::load()"); } +void Shader::_setUniform(Uniform *u) +{ + /*if(u->location == -1) + { + u->location = glGetUniformLocationARB(g_programObj, u->name); + if(u->location == -1) + { + u->dirty = false; + return; + } + }*/ + switch(u->type) + { + case GL_FLOAT: glUniform1fvARB(u->location, 1, u->data.f); break; + case GL_FLOAT_VEC2_ARB: glUniform2fvARB(u->location, 1, u->data.f); break; + case GL_FLOAT_VEC3_ARB: glUniform3fvARB(u->location, 1, u->data.f); break; + case GL_FLOAT_VEC4_ARB: glUniform4fvARB(u->location, 1, u->data.f); break; + case GL_INT: glUniform1ivARB(u->location, 1, u->data.i); break; + case GL_INT_VEC2_ARB: glUniform2ivARB(u->location, 1, u->data.i); break; + case GL_INT_VEC3_ARB: glUniform3ivARB(u->location, 1, u->data.i); break; + case GL_INT_VEC4_ARB: glUniform4ivARB(u->location, 1, u->data.i); break; + } + u->dirty = false; +} + +void Shader::_flushUniforms() +{ + if(!uniformsDirty) + return; + uniformsDirty = false; + + for(size_t i = 0; i < uniforms.size(); ++i) + { + Uniform &u = uniforms[i]; + if(u.dirty) + _setUniform(&u); + } +} + +// for sorting +bool Shader::_sortUniform(const Uniform& a, const char *bname) +{ + return strcmp(a.name, bname) < 0; +} + +bool Shader::Uniform::operator< (const Uniform& b) const +{ + return Shader::_sortUniform(*this, &b.name[0]); +} + +void Shader::_queryUniforms() +{ + glGetObjectParameterivARB(g_programObj, GL_OBJECT_ACTIVE_UNIFORMS_ARB , &numUniforms); + + if (numUniforms <= 0) + return; + + uniforms.reserve(numUniforms); + + for (unsigned int i = 0; i < numUniforms; ++i) + { + Uniform u; + GLint size = 0; + GLenum type = 0; + glGetActiveUniformARB(g_programObj, i, sizeof(u.name), NULL, &size, &type, &u.name[0]); + if(!type || !size) + continue; + u.location = glGetUniformLocationARB(g_programObj, u.name); + if(u.location == -1) + continue; + u.dirty = false; + u.type = type; + memset(&u.data, 0, sizeof(u.data)); + + uniforms.push_back(u); + } + + // sort to be able to do binary search later + std::sort(uniforms.begin(), uniforms.end()); +} + +int Shader::_getUniformIndex(const char *name) +{ + // binary search + UniformVec::iterator it = stdx_fg::lower_bound(uniforms.begin(), uniforms.end(), name, _sortUniform); + // because lower_bound returns the first element that compares less, it might not be the correct one + if(it != uniforms.end() && strcmp(it->name, name)) + return -1; + return int(it - uniforms.begin()); +} + +void Shader::setInt(const char *name, int x, int y /* = 0 */, int z /* = 0 */, int w /* = 0 */) +{ +#if BBGE_BUILD_SHADERS + if(!g_programObj || numUniforms <= 0) + return; + int idx = _getUniformIndex(name); + if(unsigned(idx) >= uniforms.size()) + return; + Uniform& u = uniforms[idx]; + u.data.i[0] = x; + u.data.i[1] = y; + u.data.i[2] = z; + u.data.i[3] = w; + u.dirty = true; + uniformsDirty = true; +#endif +} + +void Shader::setFloat(const char *name, float x, float y /* = 0 */, float z /* = 0 */, float w /* = 0 */) +{ +#if BBGE_BUILD_SHADERS + if(!g_programObj || numUniforms <= 0) + return; + int idx = _getUniformIndex(name); + if(unsigned(idx) >= uniforms.size()) + return; + Uniform& u = uniforms[idx]; + u.data.f[0] = x; + u.data.f[1] = y; + u.data.f[2] = z; + u.data.f[3] = w; + u.dirty = true; + uniformsDirty = true; +#endif +} diff --git a/BBGE/Shader.h b/BBGE/Shader.h index 1eb4cd9..2b978e7 100644 --- a/BBGE/Shader.h +++ b/BBGE/Shader.h @@ -22,36 +22,74 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define BBGE_SHADER_H #include "Base.h" +#include "ScriptObject.h" class Shader { public: Shader(); ~Shader(); - bool isLoaded(); + bool isLoaded() const; void load(const std::string &file, const std::string &fragFile); + void loadSrc(const char *vertCode, const char *fragCode); void reload(); + void unload(); void bind(); void unbind(); - void setMode(int mode); - void setValue(float x, float y, float z, float w); - std::string vertFile, fragFile; + + void setInt(const char *name, int x, int y = 0, int z = 0, int w = 0); + void setFloat(const char *name, float x, float y = 0, float z = 0, float w = 0); + // TODO: other setters needed? + + protected: + std::string vertFile, fragFile; #ifdef BBGE_BUILD_OPENGL GLuint g_programObj; - GLuint g_vertexShader; - GLuint g_fragmentShader; - GLuint g_location_texture; - GLuint g_location_mode; - GLuint g_location_value; + int numUniforms; #endif - int mode; - float vx, vy, vz, vw; - bool loaded; +private: static void staticInit(); static bool _wasInited; static bool _useShaders; + + static unsigned int _compileShader(int type, const char *src, char *errbuf, size_t errbufsize); + + struct Uniform + { + int location; // GL location variable + int type; + bool dirty; // need to flush if true + union + { + struct + { + int i[4]; + }; + struct + { + float f[4]; + }; + } data; + char name[32]; + + bool operator< (const Uniform&) const; + }; + + static bool _sortUniform(const Uniform& a, const char *bname); + + void _queryUniforms(); + void _flushUniforms(); + void _registerUniform(); + + void _setUniform(Uniform *u); + int _getUniformIndex(const char *name); + + typedef std::vector UniformVec; + UniformVec uniforms; + + bool uniformsDirty; }; #endif diff --git a/BBGE/SkeletalSprite.cpp b/BBGE/SkeletalSprite.cpp index c37744f..ea0a5d3 100644 --- a/BBGE/SkeletalSprite.cpp +++ b/BBGE/SkeletalSprite.cpp @@ -507,8 +507,7 @@ Animation* AnimationLayer::getCurrentAnimation() { std::ostringstream os; os << "skel: " << s->filenameLoaded << " currentAnimation: " << currentAnimation << " is out of range\n error in anim file?"; - errorLog(os.str()); - exit(-1); + exit_error(os.str()); return 0; } return &s->animations[currentAnimation]; diff --git a/BBGE/StateManager.cpp b/BBGE/StateManager.cpp index 8845e4f..f0a81ad 100644 --- a/BBGE/StateManager.cpp +++ b/BBGE/StateManager.cpp @@ -279,7 +279,7 @@ void StateManager::registerStateObject(StateObject *stateObject, const std::stri //getNameFromDerivedClassTypeName(c); if (stateObject->name.empty()) { - fatalError("StateManager::registerStateObject - Empty name."); + exit_error("StateManager::registerStateObject - Empty name."); } if (!stateObjects[stateObject->name]) diff --git a/BBGE/Texture.cpp b/BBGE/Texture.cpp index a15e69c..97cd22b 100644 --- a/BBGE/Texture.cpp +++ b/BBGE/Texture.cpp @@ -446,7 +446,6 @@ void Texture::loadPNG(const std::string &file) width = 64; height = 64; Texture::textureError = TEXERR_FILENOTFOUND; - //exit(1); return; } @@ -483,7 +482,6 @@ void Texture::loadPNG(const std::string &file) width = 64; height = 64; Texture::textureError = TEXERR_FILENOTFOUND; - //exit(1); } diff --git a/BBGE/Vector.cpp b/BBGE/Vector.cpp index 94eeb49..73b24bc 100644 --- a/BBGE/Vector.cpp +++ b/BBGE/Vector.cpp @@ -306,12 +306,12 @@ Vector VectorPath::getValue(float usePercent) if (!from && !target) { - msg ("returning first value"); + errorLog("returning first value"); return pathNodes[0].value; } else if (!from && target) { - msg("Unexpected Path node result (UPDATE: Could use current value as from?)"); + errorLog("Unexpected Path node result (UPDATE: Could use current value as from?)"); } else if (from && !target) { diff --git a/CMakeLists.txt b/CMakeLists.txt index 8581adb..624c0e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -243,7 +243,7 @@ ADD_DEFINITIONS(-DTIXML_USE_STL=1) ADD_DEFINITIONS(-DBBGE_SKIP_CONFIG_HEADERS=1) # if this is not defined, it will use .h files to set the necessary defines ADD_DEFINITIONS(-DBBGE_BUILD_SDL=1) ADD_DEFINITIONS(-DBBGE_BUILD_FRAMEBUFFER=1) -#ADD_DEFINITIONS(-DBBGE_BUILD_SHADERS=1) +ADD_DEFINITIONS(-DBBGE_BUILD_SHADERS=1) ADD_DEFINITIONS(-DBBGE_BUILD_OPENGL=1) ADD_DEFINITIONS(-DBBGE_BUILD_OPENGL_DYNAMIC=1) ADD_DEFINITIONS(-DBBGE_BUILD_FMOD_OPENAL_BRIDGE=1) diff --git a/ExternalLibs/algorithmx.h b/ExternalLibs/algorithmx.h new file mode 100644 index 0000000..44f85a0 --- /dev/null +++ b/ExternalLibs/algorithmx.h @@ -0,0 +1,34 @@ +#ifndef STDXfg_ALGORITHMX_H +#define STDXfg_ALGORITHMX_H + +// Some std:: namespace enhancements + +#include + +namespace stdx_fg { + +template +ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& val, Compare comp) +{ + ForwardIterator it; + typename std::iterator_traits::difference_type count, step; + count = std::distance(first,last); + while(count > 0) + { + it = first; + step = count/2; + std::advance (it,step); + if (comp(*it, val)) + { + first= ++it; + count -= step+1; + } + else + count = step; + } + return first; +} + +} // end namespace stdx_fg + +#endif diff --git a/files/data/worldmap.txt b/files/data/worldmap.txt new file mode 100644 index 0000000..f82cc39 --- /dev/null +++ b/files/data/worldmap.txt @@ -0,0 +1,56 @@ +0 1008 MAINAREA 0 5 -0.667596 -1.2 1 1 +1 1006 NAIJACAVE 1 2.5 398.484 -188.954 1 1 +2 1005 VEDHACAVE 1 2 14.4108 -19.2 1 0.36 +3 1015 ABYSS01 0 5 319.096 639.447 0 1 +4 1015 ABYSS03 0 5 638.433 637.068 0 1 +5 1009 OPENWATER02 0 5 319.17 -0.0658667 0 1 +6 1009 OPENWATER03 0 5 638.633 -0.399733 0 1 +7 1009 OPENWATER04 0 5 319.025 319.734 0 1 +8 1009 OPENWATER06 0 5 638.63 317.827 0 1 +9 1007 SONGCAVE02 1 2 128.578 159.092 0 0.387867 +10 1007 SONGCAVE 1 5 118.842 147.471 0 0.599717 +11 1014 VEIL01 0 5 638.579 -639.354 0 1 +12 1014 VEIL02 0 5 958.132 -639.401 0 1 +13 1009 VEIL03 0 5 638.221 -319.998 0 1 +14 1010 FOREST02 0 5 -0.0961994 -639.541 0 1 +15 1010 FOREST03 0 5 319.841 -639.163 0 1 +16 1010 FOREST04 0 5 -0.0881051 -320.302 0 1 +17 1010 FOREST05 0 5 319.692 -320.261 0 1 +18 1025 FORESTSPRITECAVE 1 2 295.55 -631.495 0 0.45125 +19 1026 FISHCAVE 1 2 -18.0111 -342.826 0 0.51796 +20 1013 SUNTEMPLE 1 5 961.345 -687.826 0 0.22643 +21 1016 SUNKENCITY01 1 2.5 -40.8617 906.841 0 1 +22 1016 SUNKENCITY02 1 5 116.437 802.774 0 1 +23 1000 BOILERROOM 1 2 49.228 940.225 0 1 +24 1004 ENERGYTEMPLE01 1 2.5 -168.536 -8.8143 0 1 +25 1004 ENERGYTEMPLE02 1 0.5 -232.22 -0.657245 0 1 +26 1004 ENERGYTEMPLE03 1 2.5 -110.834 56.4481 0 1 +27 1004 ENERGYTEMPLE04 1 4 -246.593 145.535 0 1 +28 1004 ENERGYTEMPLE05 1 2 -207.873 175.936 0 1 +29 1004 ENERGYTEMPLE06 1 2 -225.836 41.8167 0 1 +30 1011 MITHALAS01 0 5 958.305 -0.399733 0 1 +31 1011 MITHALAS02 1 5 1178.23 40.9613 0 1 +32 1012 CATHEDRAL02 1 5 1458.63 70.988 0 1 +33 1012 CATHEDRAL03 1 5 1491.23 315.666 0 1 +34 1012 CATHEDRAL04 1 5 1231.44 457.454 0 1 +35 1029 LICAVE 1 2 796.398 -663.693 0 0.500888 +36 1013 SUNWORMTEST 1 4 987.255 -699.643 0 0.213937 +37 1010 TREE02 0 2 -11.9703 -830.088 0 1 +38 1028 SEAHORSE 1 5 803.549 308.257 0 1 +39 1027 TURTLECAVE 1 5 371.817 -730.55 0 1 +40 1019 ICECAVE 1 5 917.784 686.531 0 1 +41 1002 FROZENVEIL 0 5 1646.98 -590.166 0 1 +42 1003 BUBBLECAVE02 1 5 1841.07 -709.693 0 1 +43 1024 MERMOGCAVE 1 2 482.591 -781.434 0 1 +44 1023 TRAININGCAVE 1 4 247.338 -85.5629 1 1 +45 1021 FINAL01 1 5 398.925 949.441 0 1 +46 1021 FINAL02 1 5 79.3004 949.894 0 1 +47 1021 FINAL03 1 5 718.257 958.177 0 1 +48 1021 FINAL04 1 5 402.406 1269.56 0 1 +49 1021 FINALBOSS 1 5 667.938 1486.98 0 1 +50 1018 OCTOCAVE 1 2 834.888 -606.756 0 0.831527 +51 1009 OPENWATER05 0 5 270.156 327.801 0 1.01408 +52 1020 THIRTEENLAIR 1 5 417.62 -121.396 0 1 +53 1030 KINGJELLYCAVE 1 2 328.989 605.32 0 0.356187 +54 1020 WEIRDCAVE 1 0.5 548.557 709.137 0 1 +55 1001 WHALE 1 2.52755 505.274 741.664 0 0.526182 diff --git a/files/gfx/gui/worldmap/whale.png b/files/gfx/gui/worldmap/whale.png new file mode 100644 index 0000000..016b8d1 Binary files /dev/null and b/files/gfx/gui/worldmap/whale.png differ diff --git a/game_scripts/scripts/entities/cc_sunkencity.lua b/game_scripts/scripts/entities/cc_sunkencity.lua index 264bfc9..d793215 100644 --- a/game_scripts/scripts/entities/cc_sunkencity.lua +++ b/game_scripts/scripts/entities/cc_sunkencity.lua @@ -220,7 +220,10 @@ function postInit(me) updateLocation(me) end +-- Both exist. Different spelling. Yay for consistency. +-- Keeping them both, should ensure behavior as it used to be, just without warnings. -- FG v.incutscene = false +v.inCutScene = false local function cutsceneintro(me, node) v.incutscene = true diff --git a/game_scripts/scripts/entities/energyboss.lua b/game_scripts/scripts/entities/energyboss.lua index 519babe..d2a6b2f 100644 --- a/game_scripts/scripts/entities/energyboss.lua +++ b/game_scripts/scripts/entities/energyboss.lua @@ -367,7 +367,7 @@ function update(me, dt) end end if entity_isState(me, STATE_MOVING) and entity_x(me) >= node_x(v.maxMove) then - if entity_isInterpolating() then + if entity_isInterpolating(me) then entity_animate(me, "idle") end entity_stopInterpolating(me) @@ -400,7 +400,7 @@ function enterState(me) entity_stopInterpolating(me) entity_animate(me, "idle", LOOP_INF) elseif entity_isState(me, STATE_ATTACK) then - playSfx("EnergyBoss-Attack", 900+math.random(200)) + playSfx("EnergyBoss-Attack", (900+math.random(200)) / 1000) local x, y = bone_getPosition(v.bone_jaw) if entity_isPositionInRange(v.naija, x, y, 600) and entity_y(v.naija) < y+64 @@ -441,12 +441,12 @@ function enterState(me) end v.attackDelay = 0 v.fireDelay = 0 - playSfx("EnergyBoss-Hurt", 900+math.random(200)) + playSfx("EnergyBoss-Hurt", (900+math.random(200)) / 1000) entity_animate(me, "hurt") entity_setPosition(me, entity_x(me)-500, entity_y(me), 1.6) elseif entity_isState(me, STATE_HITBARRIER) then entity_stopInterpolating(me) - playSfx("EnergyBoss-Die", 1100+math.random(200)) + playSfx("EnergyBoss-Die", (1100+math.random(200)) / 1000) entity_animate(me, "hitBarrier") entity_spawnParticlesFromCollisionMask(me, "energyboss-hit", 4) @@ -459,7 +459,7 @@ function enterState(me) entity_setPosition(me, node_x(backNode), entity_y(me), -800) elseif entity_isState(me, STATE_COLLAPSE) then clearShots() - playSfx("EnergyBoss-Die", 1000) + playSfx("EnergyBoss-Die") setFlag(FLAG_ENERGYBOSSDEAD, 1) entity_setDamageTarget(me, DT_AVATAR_ENERGYBLAST, false) entity_setDamageTarget(me, DT_AVATAR_SHOCK, false) @@ -504,7 +504,7 @@ function enterState(me) --end elseif entity_isState(me, STATE_INTRO) then v.awoken = true - playSfx("EnergyBoss-Die", 800) + playSfx("EnergyBoss-Die", 0.8) shakeCamera(10, 3) entity_stopInterpolating(me) entity_animate(me, "roar") diff --git a/game_scripts/scripts/entities/pet_piranha.lua b/game_scripts/scripts/entities/pet_piranha.lua index 0bf82f7..fb8ec02 100644 --- a/game_scripts/scripts/entities/pet_piranha.lua +++ b/game_scripts/scripts/entities/pet_piranha.lua @@ -132,15 +132,17 @@ function update(me, dt) if entity_hasTarget(me) then target = entity_getTarget(me) - --[[ - ox, oy = entity_getOffset(target) - cx = entity_x(target) + ox + entity_velx(target) - cy = entity_y(target) + oy + entity_vely(target) - ]]-- - cx, cy = entity_getTargetPoint(target, v.tpoint) - cx = cx + entity_velx(target) - cy = cy + entity_vely(target) - dist = 40 + if target ~= 0 then + --[[ + ox, oy = entity_getOffset(target) + cx = entity_x(target) + ox + entity_velx(target) + cy = entity_y(target) + oy + entity_vely(target) + ]]-- + cx, cy = entity_getTargetPoint(target, v.tpoint) + cx = cx + entity_velx(target) + cy = cy + entity_vely(target) + dist = 40 + end --debugLog(string.format("distTimer: %f", v.distTimer)) v.distTimer = v.distTimer + dt * 0.5 @@ -160,8 +162,10 @@ function update(me, dt) end end - entity_flipToEntity(me, target) - entity_rotateToEntity(me, target) + if target ~= 0 then + entity_flipToEntity(me, target) + entity_rotateToEntity(me, target) + end local a = t x = x + math.sin(a)*dist diff --git a/game_scripts/scripts/entities/predatorytunicate.lua b/game_scripts/scripts/entities/predatorytunicate.lua index 1960c0b..b6f6871 100644 --- a/game_scripts/scripts/entities/predatorytunicate.lua +++ b/game_scripts/scripts/entities/predatorytunicate.lua @@ -28,6 +28,7 @@ v.getOutHits = 0 v.hx = 0 v.hy = 0 v.hurtTimer = 0 +v.trapDelay = 0 local STATE_TRAP = 1001 local STATE_TRAPPED = 1002 diff --git a/win/vc90/BBGE.vcproj b/win/vc90/BBGE.vcproj index b6cf501..ef5d40e 100644 --- a/win/vc90/BBGE.vcproj +++ b/win/vc90/BBGE.vcproj @@ -352,10 +352,6 @@ RelativePath="..\..\BBGE\ParticleManager.cpp" > - - diff --git a/win/vc90/external.vcproj b/win/vc90/external.vcproj index 0eb936d..ef30d30 100644 --- a/win/vc90/external.vcproj +++ b/win/vc90/external.vcproj @@ -1219,6 +1219,10 @@ Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > + +