From cba3535487be473933d01a2b3eaa31731cd448b9 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Mon, 22 Apr 2013 23:36:31 +0200 Subject: [PATCH 01/50] Keep track of total number of GL render calls --- Aquaria/DSQ.cpp | 2 +- BBGE/Core.cpp | 6 +++++- BBGE/Core.h | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Aquaria/DSQ.cpp b/Aquaria/DSQ.cpp index bc4fff4..d58645f 100644 --- a/Aquaria/DSQ.cpp +++ b/Aquaria/DSQ.cpp @@ -4590,7 +4590,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/BBGE/Core.cpp b/BBGE/Core.cpp index b71581c..3bb0f1e 100644 --- a/BBGE/Core.cpp +++ b/BBGE/Core.cpp @@ -1840,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 @@ -3006,6 +3008,8 @@ void Core::main(float runTime) updateCullData(); + dbg_numRenderCalls = 0; + if (settings.renderOn) { if (verbose) debugLog("dark layer prerender"); diff --git a/BBGE/Core.h b/BBGE/Core.h index 84b08cb..8e45ab3 100644 --- a/BBGE/Core.h +++ b/BBGE/Core.h @@ -1310,6 +1310,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: From 0490afe7a28623349afd4a4e7f6a71a2dfbceb9e Mon Sep 17 00:00:00 2001 From: fgenesis Date: Mon, 22 Apr 2013 23:38:10 +0200 Subject: [PATCH 02/50] Script interface additions: + entity_isDeathScene() + getNearestEntity() + entity_getDistanceToPoint() Add color transition time parameter to fade(), fade2(), fade3() --- Aquaria/Entity.h | 1 + Aquaria/ScriptInterface.cpp | 41 ++++++++++++++++++++++++++++++++++--- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/Aquaria/Entity.h b/Aquaria/Entity.h index 336ccf3..724aa64 100644 --- a/Aquaria/Entity.h +++ b/Aquaria/Entity.h @@ -436,6 +436,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)); diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index 5ea30bc..f6e801e 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -4564,6 +4564,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); @@ -5204,6 +5216,12 @@ luaFunc(entity_setDeathScene) luaReturnNil(); } +luaFunc(entity_isDeathScene) +{ + Entity *e = entity(L); + luaReturnBool(e ? e->isDeathScene() : false); +} + luaFunc(entity_setCurrentTarget) { Entity *e = entity(L); @@ -6546,6 +6564,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); @@ -7049,21 +7081,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(); } @@ -7557,6 +7589,7 @@ static const struct { luaRegister(entity_setBoneLock), luaRegister(entity_setIngredient), luaRegister(entity_setDeathScene), + luaRegister(entity_isDeathScene), luaRegister(entity_setBeautyFlip), luaRegister(entity_setInvincible), @@ -7708,6 +7741,7 @@ static const struct { luaRegister(entity_getVectorToEntity), luaRegister(entity_getDistanceToTarget), + luaRegister(entity_getDistanceToPoint), luaRegister(entity_move), luaRegister(entity_getID), @@ -8302,6 +8336,7 @@ static const struct { luaRegister(entity_getNearestEntity), luaRegister(entity_getNearestBoneToPosition), + luaRegister(getNearestEntity), luaRegister(entity_getNearestNode), luaRegister(entity_setPoison), From 405045b3fbe9553430ed068ebe74cdcdb648d5a3 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Mon, 22 Apr 2013 23:41:48 +0200 Subject: [PATCH 03/50] Do not collide shots with entity if shot->firer == entity. This check was already done if entity was ET_ENEMY, but it seems more correct to me to check this for all cases. Hope this doesn't break anything. --- Aquaria/Game.cpp | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/Aquaria/Game.cpp b/Aquaria/Game.cpp index cab97ab..bc20925 100644 --- a/Aquaria/Game.cpp +++ b/Aquaria/Game.cpp @@ -1233,6 +1233,8 @@ Game::Game() : StateObject() loadEntityTypeList(); + lastCollideMaskIndex = -1; + } @@ -8356,7 +8358,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 +8369,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) From 035ad963f5ab891fdb499358427ef70ca0064d34 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Tue, 23 Apr 2013 00:57:13 +0200 Subject: [PATCH 04/50] Add Lua func: avatar_isBlockSinging() --- Aquaria/ScriptInterface.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index f6e801e..9741251 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -2693,6 +2693,11 @@ luaFunc(avatar_setBlockSinging) luaReturnNil(); } +luaFunc(avatar_isBlockSinging) +{ + luaReturnBool(dsq->game->avatar->isBlockSinging()); +} + luaFunc(avatar_fallOffWall) { dsq->game->avatar->fallOffWall(); @@ -8049,6 +8054,7 @@ static const struct { luaRegister(avatar_fallOffWall), luaRegister(avatar_setBlockSinging), + luaRegister(avatar_isBlockSinging), luaRegister(avatar_toggleMovement), From 3ed40e73d3c102c148c708181b59de3a5fca3526 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Wed, 24 Apr 2013 04:51:26 +0200 Subject: [PATCH 05/50] Minor refactor & add Lua funcs: + avatar_setShieldActive() + entity_isFillGrid() * entity_setBoneLock() code made easier to read and not warn on no lock entity + entity_getMaxSpeedLerp() + entity_isEntityInside() --- Aquaria/Avatar.cpp | 29 +++++++++++++++++++++ Aquaria/Avatar.h | 2 ++ Aquaria/Continuity.cpp | 36 ++----------------------- Aquaria/DSQ.h | 1 - Aquaria/Entity.cpp | 11 ++++++++ Aquaria/Entity.h | 2 ++ Aquaria/ScriptInterface.cpp | 52 +++++++++++++++++++++++++++++++------ Aquaria/ScriptedEntity.cpp | 26 ------------------- Aquaria/ScriptedEntity.h | 1 - 9 files changed, 90 insertions(+), 70 deletions(-) diff --git a/Aquaria/Avatar.cpp b/Aquaria/Avatar.cpp index a4c030f..1b47b1b 100644 --- a/Aquaria/Avatar.cpp +++ b/Aquaria/Avatar.cpp @@ -4686,6 +4686,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() { diff --git a/Aquaria/Avatar.h b/Aquaria/Avatar.h index 0b8a196..d3a787e 100644 --- a/Aquaria/Avatar.h +++ b/Aquaria/Avatar.h @@ -317,6 +317,8 @@ public: bool canSetBoneLock(); void revert(); + void doBindSong(); + void doShieldSong(); int leaches; diff --git a/Aquaria/Continuity.cpp b/Aquaria/Continuity.cpp index 063dd8a..31a6ac3 100644 --- a/Aquaria/Continuity.cpp +++ b/Aquaria/Continuity.cpp @@ -1347,16 +1347,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 +1399,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); diff --git a/Aquaria/DSQ.h b/Aquaria/DSQ.h index 5043f36..e24d4ff 100644 --- a/Aquaria/DSQ.h +++ b/Aquaria/DSQ.h @@ -996,7 +996,6 @@ public: FormUpgrades formUpgrades; void loadSongBank(); - int getSongBankSize(); void loadIntoSongBank(const std::string &file); int checkSong(const Song &song); int checkSongAssisted(const Song &song); diff --git a/Aquaria/Entity.cpp b/Aquaria/Entity.cpp index 8e7f027..f0c1e8f 100644 --- a/Aquaria/Entity.cpp +++ b/Aquaria/Entity.cpp @@ -3133,3 +3133,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 724aa64..d89154e 100644 --- a/Aquaria/Entity.h +++ b/Aquaria/Entity.h @@ -489,6 +489,8 @@ public: void setHairHeadPosition(const Vector &pos); void exertHairForce(const Vector &force, float dt); + bool isEntityInside(); + protected: bool calledEntityDied; Path *waterBubble; diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index 9741251..a4e0753 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -2112,18 +2112,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); @@ -2553,6 +2557,12 @@ luaFunc(entity_setFillGrid) luaReturnNil(); } +luaFunc(entity_isFillGrid) +{ + Entity *e = entity(L); + luaReturnBool(e ? e->fillGridFromQuad : false); +} + luaFunc(entity_getAimVector) { Entity *e = entity(L); @@ -2731,6 +2741,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()); @@ -5049,6 +5069,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) @@ -6165,6 +6191,12 @@ luaFunc(entity_getDistanceToEntity) luaReturnNum(d); } +luaFunc(entity_isEntityInside) +{ + Entity *e = entity(L); + luaReturnBool(e ? e->isEntityInside() : false); +} + // entity_istargetInRange luaFunc(entity_isTargetInRange) { @@ -7844,6 +7876,7 @@ static const struct { luaRegister(entity_isTargetInRange), luaRegister(entity_getDistanceToEntity), + luaRegister(entity_isEntityInside), luaRegister(entity_isInvincible), @@ -7860,6 +7893,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), @@ -8050,6 +8084,7 @@ static const struct { luaRegister(avatar_isRolling), luaRegister(avatar_isOnWall), luaRegister(avatar_isShieldActive), + luaRegister(avatar_setShieldActive), luaRegister(avatar_getRollDirection), luaRegister(avatar_fallOffWall), @@ -8278,6 +8313,7 @@ static const struct { luaRegister(entity_setTexture), luaRegister(entity_setFillGrid), + luaRegister(entity_isFillGrid), luaRegister(entity_push), 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; From 55ead19076abb29b7ed4222206b3fd41c164a60c Mon Sep 17 00:00:00 2001 From: fgenesis Date: Thu, 25 Apr 2013 02:51:54 +0200 Subject: [PATCH 06/50] Remove spirit form dependency on WorldType, and add related Lua interfaces. This commit introduces a second pause mode: Full game pause (as in menu), and world pause (as in spirit form). All related checks are no longer done against WT_* constants, but against the new world pause which is functionally equivalent, but more flexible. Continuity::worldType is now only used to toggle world pause correctly, and to apply some related graphical effects. The world pause can also be controlled via script without actually switching forms. Added Lua functions: + node_setSpiritFreeze() + quad_setPauseLevel() + isWorldPaused() + setWorldPaused() --- Aquaria/Avatar.cpp | 13 ++++--------- Aquaria/Avatar.h | 1 - Aquaria/Continuity.cpp | 8 +++++++- Aquaria/DSQ.cpp | 1 + Aquaria/Entity.cpp | 6 +++--- Aquaria/Game.cpp | 4 ++-- Aquaria/Game.h | 4 ++++ Aquaria/Ingredient.cpp | 2 +- Aquaria/Mod.cpp | 1 + Aquaria/Path.cpp | 13 ++++--------- Aquaria/Path.h | 1 + Aquaria/ScriptInterface.cpp | 33 +++++++++++++++++++++++++++++++++ Aquaria/Shot.cpp | 2 +- BBGE/Quad.cpp | 1 + BBGE/ScriptObject.cpp | 1 + BBGE/ScriptObject.h | 1 + 16 files changed, 65 insertions(+), 27 deletions(-) diff --git a/Aquaria/Avatar.cpp b/Aquaria/Avatar.cpp index 1b47b1b..4bfb56f 100644 --- a/Aquaria/Avatar.cpp +++ b/Aquaria/Avatar.cpp @@ -752,11 +752,6 @@ bool Avatar::isSinging() return singing; } -void Avatar::shift() -{ - dsq->continuity.shiftWorlds(); -} - void Avatar::applyWorldEffects(WorldType type) { static bool oldfh=false; @@ -5275,7 +5270,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(); @@ -6205,7 +6200,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); } @@ -6439,7 +6434,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) { @@ -7156,7 +7151,7 @@ void Avatar::onUpdate(float dt) if (dsq->game->collideCircleWithGrid(position, collideRadius)) { if (dsq->game->lastCollideTileType == OT_HURT - && dsq->continuity.getWorldType() != WT_SPIRIT + && !dsq->game->isWorldPaused() && dsq->continuity.form != FORM_NATURE) { DamageData d; diff --git a/Aquaria/Avatar.h b/Aquaria/Avatar.h index d3a787e..f7be754 100644 --- a/Aquaria/Avatar.h +++ b/Aquaria/Avatar.h @@ -160,7 +160,6 @@ public: Entity *entityToActivate; Path *pathToActivate; - void shift(); void applyWorldEffects(WorldType type); void toggleMovement(bool on); diff --git a/Aquaria/Continuity.cpp b/Aquaria/Continuity.cpp index 31a6ac3..8d58c58 100644 --- a/Aquaria/Continuity.cpp +++ b/Aquaria/Continuity.cpp @@ -1916,9 +1916,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; @@ -2018,7 +2024,7 @@ void Continuity::applyWorldEffects(WorldType type, bool transition, bool affectM dsq->game->avatar->enableInput(); */ } - worldType = type; + //worldType = type; } void Continuity::eatBeast(const EatData &eatData) diff --git a/Aquaria/DSQ.cpp b/Aquaria/DSQ.cpp index d58645f..6f0079e 100644 --- a/Aquaria/DSQ.cpp +++ b/Aquaria/DSQ.cpp @@ -4576,6 +4576,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); diff --git a/Aquaria/Entity.cpp b/Aquaria/Entity.cpp index f0c1e8f..e4d464d 100644 --- a/Aquaria/Entity.cpp +++ b/Aquaria/Entity.cpp @@ -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) { diff --git a/Aquaria/Game.cpp b/Aquaria/Game.cpp index bc20925..02bb0ef 100644 --- a/Aquaria/Game.cpp +++ b/Aquaria/Game.cpp @@ -1234,7 +1234,7 @@ Game::Game() : StateObject() loadEntityTypeList(); lastCollideMaskIndex = -1; - + worldPaused = false; } @@ -5719,7 +5719,7 @@ void Game::updateParticlePause() { core->particlesPaused = 2; } - else if (dsq->continuity.getWorldType() == WT_SPIRIT) + else if (this->isWorldPaused()) { core->particlesPaused = 1; } diff --git a/Aquaria/Game.h b/Aquaria/Game.h index 33a5bc6..125b13e 100644 --- a/Aquaria/Game.h +++ b/Aquaria/Game.h @@ -1001,6 +1001,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 +1161,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/Ingredient.cpp b/Aquaria/Ingredient.cpp index d31d980..97b9e42 100644 --- a/Aquaria/Ingredient.cpp +++ b/Aquaria/Ingredient.cpp @@ -109,7 +109,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/Mod.cpp b/Aquaria/Mod.cpp index 693b9f0..beac053 100644 --- a/Aquaria/Mod.cpp +++ b/Aquaria/Mod.cpp @@ -284,6 +284,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/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index a4e0753..f6f9ed0 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -377,6 +377,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 @@ -2351,6 +2352,17 @@ luaFunc(getWorldType) luaReturnNum((int)dsq->continuity.getWorldType()); } +luaFunc(isWorldPaused) +{ + luaReturnBool(dsq->game->isWorldPaused()); +} + +luaFunc(setWorldPaused) +{ + dsq->game->setWorldPaused(getBool(L, 1)); + luaReturnNil(); +} + luaFunc(getNearestNodeByType) { int x = lua_tonumber(L, 1); @@ -2546,6 +2558,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); @@ -4755,6 +4775,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); @@ -7597,11 +7626,14 @@ static const struct { luaRegister(getNoteName), luaRegister(getWorldType), + luaRegister(setWorldPaused), + luaRegister(isWorldPaused), luaRegister(getWaterLevel), luaRegister(setWaterLevel), luaRegister(createQuad), + luaRegister(quad_setPauseLevel), luaRegister(setupEntity), luaRegister(setActivePet), @@ -7651,6 +7683,7 @@ static const struct { luaRegister(entity_setEatType), luaRegister(entity_setSpiritFreeze), + luaRegister(node_setSpiritFreeze), luaRegister(entity_setCanLeaveWater), diff --git a/Aquaria/Shot.cpp b/Aquaria/Shot.cpp index b52b762..98fac54 100644 --- a/Aquaria/Shot.cpp +++ b/Aquaria/Shot.cpp @@ -778,7 +778,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/BBGE/Quad.cpp b/BBGE/Quad.cpp index 5fa50ee..517125b 100644 --- a/BBGE/Quad.cpp +++ b/BBGE/Quad.cpp @@ -802,6 +802,7 @@ void Quad::onSetTexture() PauseQuad::PauseQuad() : Quad(), pauseLevel(0) { + addType(SCO_PAUSEQUAD); } void PauseQuad::onUpdate(float dt) diff --git a/BBGE/ScriptObject.cpp b/BBGE/ScriptObject.cpp index 452edbe..442797b 100644 --- a/BBGE/ScriptObject.cpp +++ b/BBGE/ScriptObject.cpp @@ -37,6 +37,7 @@ static const char *scriptObjTypeNames[] = /* (1 << 9) */ "Path/Node", /* (1 <<10) */ "Quad", /* (1 <<11) */ "Text", + /* (1 <<12) */ "PauseQuad", NULL }; diff --git a/BBGE/ScriptObject.h b/BBGE/ScriptObject.h index 08cd693..4c2ff20 100644 --- a/BBGE/ScriptObject.h +++ b/BBGE/ScriptObject.h @@ -39,6 +39,7 @@ enum ScriptObjectType SCO_PATH = 0x0200, SCO_QUAD = 0x0400, SCO_TEXT = 0x0800, + SCO_PAUSEQUAD = 0x1000, SCO_FORCE_32BIT = 0xFFFFFFFF }; From e8a7889f82e575ad4c5f76ab2e4078f9d343a820 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Fri, 26 Apr 2013 00:34:06 +0200 Subject: [PATCH 07/50] Decouple form specific effects from the actual form. Most hardcoded form == FORM_* checks all over the place have been replaced. Now, forms change certain avatar properties, which are in turn checked in the places that previously had these explicit form checks. This allows specifying functionality via scripting, for additional forms with new effects or a new combination of existing effects. OT_HURT now deals damage of type DT_WALLHURT, and by setting avatar->setDamageTarget(DT_WALLHURT, false) collision with walls can be made harmless (exactly as nature form used to be). Add related Lua functions: + setWorldType() - Change WT without actually switching to spirit form + setCanActivate() + avatar_setCanBurst() + avatar_canBurst() + avatar_setCanLockToWall() + avatar_canLockToWall() + avatar_setCanSwimAgainstCurrents() + avatar_canSwimAgainstCurrents() + getSceneColor() + DT_WALLHURT --- Aquaria/Avatar.cpp | 78 +++++++++++++++++-------------------- Aquaria/Avatar.h | 15 ++++++- Aquaria/Continuity.cpp | 2 +- Aquaria/DSQ.cpp | 4 ++ Aquaria/Entity.cpp | 4 +- Aquaria/Entity.h | 1 + Aquaria/ScriptInterface.cpp | 67 ++++++++++++++++++++++++++++++- 7 files changed, 124 insertions(+), 47 deletions(-) diff --git a/Aquaria/Avatar.cpp b/Aquaria/Avatar.cpp index 4bfb56f..7587178 100644 --- a/Aquaria/Avatar.cpp +++ b/Aquaria/Avatar.cpp @@ -744,7 +744,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() @@ -1590,6 +1590,7 @@ 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); } break; case FORM_SUN: @@ -1601,9 +1602,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()) @@ -1613,6 +1618,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) { @@ -1722,6 +1730,7 @@ void Avatar::changeForm(FormType form, bool effects, bool onInit, FormType lastF //refreshModel("NaijaFish", ""); collideRadius = COLLIDE_RADIUS_FISH; + setCanLockToWall(false); } break; case FORM_SUN: @@ -1753,42 +1762,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: @@ -1796,6 +1776,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) { @@ -3490,8 +3474,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; @@ -3589,7 +3573,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; } @@ -4123,6 +4107,12 @@ 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; } void Avatar::revert() @@ -4319,7 +4309,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)) { @@ -5409,7 +5399,12 @@ void Avatar::setWasUnderWater() bool Avatar::canActivateStuff() { - return dsq->continuity.form != FORM_SPIRIT; + return _canActivateStuff; +} + +void Avatar::setCanActivateStuff(bool on) +{ + _canActivateStuff = on; } bool Avatar::canQuickSong() @@ -7142,7 +7137,6 @@ void Avatar::onUpdate(float dt) else omov -= mov; - lastLastPosition = position; lastPosition = position; Vector newPosition = position + mov; //Vector testPosition = position + (vel *dt)*2; @@ -7151,11 +7145,11 @@ void Avatar::onUpdate(float dt) if (dsq->game->collideCircleWithGrid(position, collideRadius)) { if (dsq->game->lastCollideTileType == OT_HURT - && !dsq->game->isWorldPaused() - && 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); @@ -7338,7 +7332,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 f7be754..d93c2e4 100644 --- a/Aquaria/Avatar.h +++ b/Aquaria/Avatar.h @@ -283,6 +283,7 @@ public: void endOfGameState(); bool canQuickSong(); bool canActivateStuff(); + void setCanActivateStuff(bool on); bool hasThingToActivate(); float biteTimer; @@ -319,6 +320,15 @@ public: 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; } + int leaches; protected: @@ -451,7 +461,10 @@ protected: void lockToWall(); void doShock(const std::string &shotName); - Vector lastLastPosition; + bool _canActivateStuff; + bool _canBurst; + bool _canLockToWall; + bool _canSwimAgainstCurrents; }; diff --git a/Aquaria/Continuity.cpp b/Aquaria/Continuity.cpp index 8d58c58..18ee693 100644 --- a/Aquaria/Continuity.cpp +++ b/Aquaria/Continuity.cpp @@ -2024,7 +2024,7 @@ void Continuity::applyWorldEffects(WorldType type, bool transition, bool affectM dsq->game->avatar->enableInput(); */ } - //worldType = type; + worldType = type; } void Continuity::eatBeast(const EatData &eatData) diff --git a/Aquaria/DSQ.cpp b/Aquaria/DSQ.cpp index 6f0079e..77343d0 100644 --- a/Aquaria/DSQ.cpp +++ b/Aquaria/DSQ.cpp @@ -4564,6 +4564,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 diff --git a/Aquaria/Entity.cpp b/Aquaria/Entity.cpp index e4d464d..67cfd20 100644 --- a/Aquaria/Entity.cpp +++ b/Aquaria/Entity.cpp @@ -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()) diff --git a/Aquaria/Entity.h b/Aquaria/Entity.h index d89154e..2cd38c6 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 }; diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index f6f9ed0..3de9180 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -1580,6 +1580,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 ) @@ -2352,6 +2353,14 @@ 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()); @@ -2709,6 +2718,47 @@ 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(avatar_setCanBurst) +{ + dsq->game->avatar->setCanBurst(getBool(L, 1)); + luaReturnNil(); +} + +luaFunc(avatar_canBurst) +{ + luaReturnBool(dsq->game->avatar->canBurst()); +} + +luaFunc(avatar_setCanLockToWall) +{ + dsq->game->avatar->setCanBurst(getBool(L, 1)); + luaReturnNil(); +} + +luaFunc(avatar_canLockToWall) +{ + luaReturnBool(dsq->game->avatar->canBurst()); +} + +luaFunc(avatar_setCanSwimAgainstCurrents) +{ + dsq->game->avatar->setCanSwimAgainstCurrents(getBool(L, 1)); + luaReturnNil(); +} + +luaFunc(avatar_canSwimAgainstCurrents) +{ + luaReturnBool(dsq->game->avatar->canSwimAgainstCurrents()); +} + + luaFunc(avatar_toggleCape) { dsq->game->avatar->toggleCape(getBool(L,1)); @@ -3773,6 +3823,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); @@ -7626,6 +7682,7 @@ static const struct { luaRegister(getNoteName), luaRegister(getWorldType), + luaRegister(setWorldType), luaRegister(setWorldPaused), luaRegister(isWorldPaused), @@ -7704,9 +7761,16 @@ static const struct { luaRegister(avatar_setCanDie), + luaRegister(setCanActivate), 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_clampPosition), luaRegister(avatar_updatePosition), @@ -8318,7 +8382,7 @@ static const struct { luaRegister(setSceneColor), - + luaRegister(getSceneColor), luaRegister(entity_watchEntity), @@ -9129,6 +9193,7 @@ static const struct { luaConstant(DT_CRUSH), luaConstant(DT_SPIKES), luaConstant(DT_STEAM), + luaConstant(DT_WALLHURT), luaConstant(FRAME_TIME), From ec7dd94a1cfae1e61aabbf1af8c467a4acd678ee Mon Sep 17 00:00:00 2001 From: fgenesis Date: Fri, 26 Apr 2013 05:03:24 +0200 Subject: [PATCH 08/50] Forms decoupling #2. Added Lua functions: + avatar_setCanCollideWithShots() + avatar_canCollideWithShots() + avatar_setCollisionAvoidanceData() --- Aquaria/Avatar.cpp | 29 ++++++++++++++++++++++------- Aquaria/Avatar.h | 9 +++++++++ Aquaria/ScriptInterface.cpp | 20 ++++++++++++++++++++ 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/Aquaria/Avatar.cpp b/Aquaria/Avatar.cpp index 7587178..b14bcd4 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; @@ -1591,6 +1597,7 @@ void Avatar::changeForm(FormType form, bool effects, bool onInit, FormType lastF collideRadius = COLLIDE_RADIUS_NORMAL; setCanLockToWall(true); + setCollisionAvoidanceData(COLLIDE_RANGE_NORMAL, COLLIDE_MOD_NORMAL); } break; case FORM_SUN: @@ -1731,6 +1738,7 @@ void Avatar::changeForm(FormType form, bool effects, bool onInit, FormType lastF collideRadius = COLLIDE_RADIUS_FISH; setCanLockToWall(false); + setCollisionAvoidanceData(COLLIDE_RANGE_FISH, COLLIDE_MOD_FISH); } break; case FORM_SUN: @@ -4113,6 +4121,10 @@ Avatar::Avatar() : Entity(), ActionMapper() _canBurst = true; _canLockToWall = true; _canSwimAgainstCurrents = false; + _canCollideWithShots = true; + + _collisionAvoidMod = COLLIDE_MOD_NORMAL; + _collisionAvoidRange = COLLIDE_RANGE_NORMAL; } void Avatar::revert() @@ -5407,6 +5419,12 @@ void Avatar::setCanActivateStuff(bool on) _canActivateStuff = on; } +void Avatar::setCollisionAvoidanceData(int range, float mod) +{ + _collisionAvoidRange = range; + _collisionAvoidMod = mod; +} + bool Avatar::canQuickSong() { return !isSinging() && !isEntityDead() && isInputEnabled() && quickSongCastDelay <= 0; @@ -7073,13 +7091,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()) @@ -7312,7 +7326,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)); } diff --git a/Aquaria/Avatar.h b/Aquaria/Avatar.h index d93c2e4..afad10d 100644 --- a/Aquaria/Avatar.h +++ b/Aquaria/Avatar.h @@ -329,6 +329,11 @@ public: 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); + int leaches; protected: @@ -465,6 +470,10 @@ protected: bool _canBurst; bool _canLockToWall; bool _canSwimAgainstCurrents; + bool _canCollideWithShots; + + int _collisionAvoidRange; + float _collisionAvoidMod; }; diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index 3de9180..93d3c6c 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -2758,6 +2758,23 @@ 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) { @@ -7771,6 +7788,9 @@ static const struct { luaRegister(avatar_canBurst), luaRegister(avatar_setCanSwimAgainstCurrents), luaRegister(avatar_canSwimAgainstCurrents), + luaRegister(avatar_setCanCollideWithShots), + luaRegister(avatar_canCollideWithShots), + luaRegister(avatar_setCollisionAvoidanceData), luaRegister(avatar_clampPosition), luaRegister(avatar_updatePosition), From a52b26c782a6b1407bfb2ea443858d70d1f660df Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sat, 27 Apr 2013 01:12:50 +0200 Subject: [PATCH 09/50] Forms decoupling #3. Added Lua functions: + setSeeMapMode() --- Aquaria/Avatar.cpp | 6 ++---- Aquaria/Avatar.h | 11 +++++++++++ Aquaria/MiniMapRender.cpp | 12 ++++++++++-- Aquaria/ScriptInterface.cpp | 11 ++++++++++- 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/Aquaria/Avatar.cpp b/Aquaria/Avatar.cpp index b14bcd4..dd2cb05 100644 --- a/Aquaria/Avatar.cpp +++ b/Aquaria/Avatar.cpp @@ -4125,6 +4125,8 @@ Avatar::Avatar() : Entity(), ActionMapper() _collisionAvoidMod = COLLIDE_MOD_NORMAL; _collisionAvoidRange = COLLIDE_RANGE_NORMAL; + + _seeMapMode = SEE_MAP_DEFAULT; } void Avatar::revert() @@ -4884,10 +4886,6 @@ void Avatar::clampVelocity() } } - - - - if (!inCurrent || (inCurrent && withCurrent)) { if (dsq->continuity.form == FORM_FISH) diff --git a/Aquaria/Avatar.h b/Aquaria/Avatar.h index afad10d..28ed710 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: @@ -334,6 +341,9 @@ public: void setCollisionAvoidanceData(int range, float mod); + void setSeeMapMode(SeeMapMode mode) { _seeMapMode = mode; } + SeeMapMode getSeeMapMode() const { return _seeMapMode; } + int leaches; protected: @@ -471,6 +481,7 @@ protected: bool _canLockToWall; bool _canSwimAgainstCurrents; bool _canCollideWithShots; + SeeMapMode _seeMapMode; int _collisionAvoidRange; float _collisionAvoidMod; 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/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index 93d3c6c..e9506b7 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -2725,6 +2725,12 @@ luaFunc(setCanActivate) luaReturnNil(); } +luaFunc(setSeeMapMode) +{ + dsq->game->avatar->setSeeMapMode((SeeMapMode)lua_tointeger(L, 1)); + luaReturnNil(); +} + luaFunc(avatar_setCanBurst) { dsq->game->avatar->setCanBurst(getBool(L, 1)); @@ -2775,7 +2781,6 @@ luaFunc(avatar_setCollisionAvoidanceData) luaReturnNil(); } - luaFunc(avatar_toggleCape) { dsq->game->avatar->toggleCape(getBool(L,1)); @@ -9241,6 +9246,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), }; //============================================================================================ From 4c8fc05de8a5ec5182f1c1c7135f3c28975a46ad Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sun, 28 Apr 2013 22:33:59 +0200 Subject: [PATCH 10/50] Fix sound problems in energyboss and warning in predatorytunicate script. Thx Diablodoct0r for reporting the latter. --- game_scripts/scripts/entities/energyboss.lua | 12 ++++++------ game_scripts/scripts/entities/predatorytunicate.lua | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) 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/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 From 7d158f5f1ceb49aa71a3970eef30d8e83c92feb3 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sun, 28 Apr 2013 22:44:28 +0200 Subject: [PATCH 11/50] Fix typos in a52b26c782a6 --- Aquaria/Avatar.h | 2 +- Aquaria/ScriptInterface.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Aquaria/Avatar.h b/Aquaria/Avatar.h index 28ed710..dea3095 100644 --- a/Aquaria/Avatar.h +++ b/Aquaria/Avatar.h @@ -71,7 +71,7 @@ enum SeeMapMode SEE_MAP_NEVER = 0, SEE_MAP_DEFAULT = 1, SEE_MAP_ALWAYS = 2, -} +}; class SongIconParticle : public Quad { diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index e9506b7..d6b4ca4 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -7784,6 +7784,7 @@ static const struct { luaRegister(avatar_setCanDie), luaRegister(setCanActivate), + luaRegister(setSeeMapMode), luaRegister(avatar_toggleCape), luaRegister(avatar_setPullTarget), From a6929c51f288415a527c1cf3c4ee478188ac514a Mon Sep 17 00:00:00 2001 From: fgenesis Date: Tue, 30 Apr 2013 00:50:45 +0200 Subject: [PATCH 12/50] Fix bug introduced in 0784d1b9dff. Thx Diablodoct0r for reporting. Not sure if bug was harmless, maybe... --- Aquaria/Shot.cpp | 8 +++++++- Aquaria/Shot.h | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Aquaria/Shot.cpp b/Aquaria/Shot.cpp index 98fac54..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() 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: From 811b015983df68ea785283956e728df72873e43d Mon Sep 17 00:00:00 2001 From: fgenesis Date: Thu, 2 May 2013 01:53:15 +0200 Subject: [PATCH 13/50] "Fix" warning in cc_sunkencity.lua Thx Diablodoct0r for reporting. --- game_scripts/scripts/entities/cc_sunkencity.lua | 3 +++ 1 file changed, 3 insertions(+) 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 From 12ea97f051b01b4ec1b52afaf68fd642bd610b98 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Thu, 2 May 2013 04:31:07 +0200 Subject: [PATCH 14/50] Disable all glEnable/glDisable() calls for GL_CULL_FACE, except one glDisable() during renderer init. GL_CULL_FACE is effectively always disabled, except for quad strip rendering, and keeping GL_CULL_FACE disabled there does not seem to cause any visual artifacts. Instead, it enhances skeletal animation possibilities (e.g. flipping bone strips over without it disappearing) --- Aquaria/Beam.cpp | 2 +- Aquaria/CurrentRender.cpp | 4 ++-- Aquaria/Hair.cpp | 4 ++-- Aquaria/SteamRender.cpp | 4 ++-- Aquaria/Web.cpp | 2 +- Aquaria/WorldMapRender.cpp | 6 +++--- BBGE/Base.cpp | 4 ++-- BBGE/BitmapFont.cpp | 4 ++-- BBGE/Emitter.cpp | 2 +- BBGE/Quad.cpp | 4 ++-- BBGE/QuadTrail.cpp | 2 +- BBGE/RenderObject.cpp | 6 +++--- BBGE/RoundedRect.cpp | 4 ++-- 13 files changed, 24 insertions(+), 24 deletions(-) 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/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/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/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/Web.cpp b/Aquaria/Web.cpp index 262df92..1e25a31 100644 --- a/Aquaria/Web.cpp +++ b/Aquaria/Web.cpp @@ -150,7 +150,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/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/Base.cpp b/BBGE/Base.cpp index ebaa09c..6feee42 100644 --- a/BBGE/Base.cpp +++ b/BBGE/Base.cpp @@ -301,7 +301,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,7 +312,7 @@ void drawCircle(float radius, int stepSize) } glEnd(); - glEnable(GL_CULL_FACE); + //glEnable(GL_CULL_FACE); #endif } 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/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/Quad.cpp b/BBGE/Quad.cpp index 517125b..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); 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() From 45821d15ffc30432248d8b6b1bdd50d256c6652b Mon Sep 17 00:00:00 2001 From: fgenesis Date: Thu, 2 May 2013 23:30:06 +0200 Subject: [PATCH 15/50] Fix regression from 7ff0caaed8. This fixes a glitch in the final boss' last form. Due to a missing Beam::trace() call, the beam's angle was not updated, and it always pointed into the upper left corner. --- Aquaria/ScriptInterface.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index d6b4ca4..d101194 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -3758,6 +3758,19 @@ luaFunc(beam_setFirer) luaReturnNil(); } +// Note the additional trace() call +luaFunc(beam_setPosition_override) +{ + Beam *b = beam(L); + if (b) + { + b->position.interpolateTo(Vector(lua_tonumber(L, 2), lua_tonumber(L, 3)), + lua_tonumber(L, 4), lua_tonumber(L, 5), lua_tonumber(L, 6), lua_tonumber(L, 7)); + b->trace(); + } + luaReturnNil(); +} + luaFunc(getStringBank) { luaReturnStr(dsq->continuity.stringBank.get(lua_tointeger(L, 1)).c_str()); @@ -8566,6 +8579,7 @@ static const struct { {"bone_getPosition", l_bone_getWorldPosition}, { "entity_delete", l_entity_delete_override }, { "entity_setRenderPass", l_entity_setRenderPass_override }, + { "beam_setPosition", l_beam_setPosition_override }, // -- deprecated/compatibility related functions below here -- From c62d9f2370b2a12713ecb5beedbdb54405eeaad7 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Fri, 10 May 2013 22:22:35 +0200 Subject: [PATCH 16/50] Re-introduce AfterEffect shader functonality, part 1. This repairs pixel/vertex shader code that was seemingly experimented with during testing, but it was never used and no shaders ever made it to the data files. --- Aquaria/DSQ.cpp | 4 +- Aquaria/Entity.cpp | 23 +-- Aquaria/Entity.h | 4 +- Aquaria/Game.cpp | 4 +- Aquaria/Game.h | 3 +- BBGE/BBGECompileConfig.h | 2 +- BBGE/Shader.cpp | 408 ++++++++++++++++++--------------------- BBGE/Shader.h | 24 +-- 8 files changed, 216 insertions(+), 256 deletions(-) diff --git a/Aquaria/DSQ.cpp b/Aquaria/DSQ.cpp index 77343d0..99427b2 100644 --- a/Aquaria/DSQ.cpp +++ b/Aquaria/DSQ.cpp @@ -1532,10 +1532,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); diff --git a/Aquaria/Entity.cpp b/Aquaria/Entity.cpp index 67cfd20..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; } @@ -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; diff --git a/Aquaria/Entity.h b/Aquaria/Entity.h index 2cd38c6..70c7a51 100644 --- a/Aquaria/Entity.h +++ b/Aquaria/Entity.h @@ -452,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(); @@ -518,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 02bb0ef..733399b 100644 --- a/Aquaria/Game.cpp +++ b/Aquaria/Game.cpp @@ -9972,7 +9972,7 @@ void Game::update(float dt) if (avatar) { - tintColor.update(dt); + /*tintColor.update(dt); if (core->afterEffectManager) { if (tintColor.isInterpolating()) @@ -9981,7 +9981,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)); diff --git a/Aquaria/Game.h b/Aquaria/Game.h index 125b13e..d9c103e 100644 --- a/Aquaria/Game.h +++ b/Aquaria/Game.h @@ -892,7 +892,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; 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/Shader.cpp b/BBGE/Shader.cpp index 90c7c5e..99a2e7c 100644 --- a/BBGE/Shader.cpp +++ b/BBGE/Shader.cpp @@ -18,10 +18,8 @@ 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 #ifdef BBGE_BUILD_SHADERS // GL_ARB_shader_objects @@ -38,6 +36,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB = NULL; PFNGLUNIFORM4FARBPROC glUniform4fARB = NULL; PFNGLUNIFORM1IARBPROC glUniform1iARB = NULL; + PFNGLUNIFORM1FARBPROC glUniform1fARB = NULL; #endif bool Shader::_wasInited = false; @@ -73,22 +72,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"); @@ -103,13 +86,14 @@ void Shader::staticInit() glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)SDL_GL_GetProcAddress("glGetUniformLocationARB"); glUniform4fARB = (PFNGLUNIFORM4FARBPROC)SDL_GL_GetProcAddress("glUniform4fARB"); glUniform1iARB = (PFNGLUNIFORM1IARBPROC)SDL_GL_GetProcAddress("glUniform1iARB"); + glUniform1fARB = (PFNGLUNIFORM1FARBPROC)SDL_GL_GetProcAddress("glUniform1fARB"); #endif if( !glCreateProgramObjectARB || !glDeleteObjectARB || !glUseProgramObjectARB || !glCreateShaderObjectARB || !glCreateShaderObjectARB || !glCompileShaderARB || !glGetObjectParameterivARB || !glAttachObjectARB || !glGetInfoLogARB || !glLinkProgramARB || !glGetUniformLocationARB || !glUniform4fARB || - !glUniform1iARB ) + !glUniform1iARB || !glUniform1fARB ) { glCreateProgramObjectARB = 0; debugLog("One or more GL_ARB_shader_objects functions were not found"); @@ -132,88 +116,32 @@ end: Shader::Shader() { - loaded = false; - mode = 0; #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() { - 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 +154,7 @@ 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); #endif } @@ -241,150 +163,190 @@ 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); + + 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; + this->vertFile = file; + this->fragFile = fragFile; - try - { + char *vertCode = file.length() ? readFile(file) : NULL; + char *fragCode = fragFile.length() ? readFile(fragFile) : NULL; - 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... - // + loadSrc(vertCode, fragCode); - const char *vertexShaderStrings[1]; - const char *fragmentShaderStrings[1]; - GLint bVertCompiled; - GLint bFragCompiled; - GLint bLinked; - char str[4096]; - - // - // 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) - { - glGetInfoLogARB(g_vertexShader, sizeof(str), NULL, str); - std::ostringstream os; - os << "Vertex Shader Compile Error: " << str; - debugLog(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 ) - { - glGetInfoLogARB( g_fragmentShader, sizeof(str), NULL, str ); - std::ostringstream os; - os << "Fragment Shader Compile Error: " << str; - debugLog(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) - { - debugLog("programObj / vertexShader / fragmentShader problem"); - return; - } - - glAttachObjectARB( g_programObj, g_vertexShader ); - glAttachObjectARB( g_programObj, g_fragmentShader ); - - // - // Link the program object and print out the info log... - // - - glLinkProgramARB( g_programObj ); - glGetObjectParameterivARB( g_programObj, GL_OBJECT_LINK_STATUS_ARB, &bLinked ); - - debugLog("Shader::load 5"); - - if( bLinked == false ) - { - glGetInfoLogARB( g_programObj, sizeof(str), NULL, str ); - std::ostringstream os; - os << "Shader Linking Error: " << str; - debugLog(os.str()); - 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; - } - catch(...) - { - debugLog("caught exception in shader::load"); - loaded = false; - } -#endif - debugLog("End Shader::load()"); + delete [] vertCode; + delete [] fragCode; } +void Shader::loadSrc(const char *vertCode, const char *fragCode) +{ + unload(); + + if(!_useShaders) + return; + +#ifdef BBGE_BUILD_SHADERS + + char str[4096]; + + GLhandleARB vertexShader = 0; + GLhandleARB fragmentShader = 0; + + // + // Create the vertex shader... + // + if(vertCode && !(vertexShader = _compileShader(GL_VERTEX_SHADER_ARB, vertCode, str, sizeof(str)))) + { + std::ostringstream os; + os << "Vertex Shader Compile Error [" << vertFile << "]:\n" << str; + errorLog(os.str()); + return; + } + + // + // Create the fragment shader... + // + if(fragCode && !(fragmentShader = _compileShader(GL_FRAGMENT_SHADER_ARB, fragCode, str, sizeof(str)))) + { + std::ostringstream os; + os << "Fragment Shader Compile Error [" << fragFile << "]:\n" << str; + errorLog(os.str()); + return; + } + + // + // Create a program object and attach the two compiled shaders... + // + + g_programObj = glCreateProgramObjectARB(); + + if (!(g_programObj && (vertexShader || fragmentShader))) + { + errorLog("programObj / vertexShader / fragmentShader problem"); + unload(); + return; + } + + // + // 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 ); + + + if(!bLinked) + { + glGetInfoLogARB( g_programObj, sizeof(str), NULL, str ); + std::ostringstream os; + os << "Shader Linking Error: " << str; + errorLog(os.str()); + unload(); + return; + } + +#endif +} + +// TODO: I'm not quite sure but i bet this sucks. +// Design a good caching policy and simplify the implementation, +// but keep shader dynamism and shaders generated at runtime in mind. +// No idea if and how much runtime performance it costs +// to query the uniform locations everytime. +// -- FG + +static void shaderUniformError(const char *func, const char *var) +{ + GLint err = glGetError(); + /*std::ostringstream os; + os << "Shader::" << func << "(" << var << ") -- undef uniform (Error: " << err << ")"; + debugLog(os.str());*/ +} + +void Shader::setInt(const char *name, int x) +{ +#if BBGE_BUILD_SHADERS + if(!g_programObj) + return; + GLint loc = glGetUniformLocationARB(g_programObj, name); + if(loc != -1) + glUniform1iARB(loc, x); + else + shaderUniformError("setInt", name); +#endif +} + +void Shader::setFloat(const char *name, float x) +{ +#if BBGE_BUILD_SHADERS + if(!g_programObj) + return; + GLint loc = glGetUniformLocationARB(g_programObj, name); + if(loc != -1) + glUniform1fARB(loc, x); + else + shaderUniformError("setFloat", name); +#endif +} + +void Shader::setFloat4(const char *name, float x, float y, float z, float w) +{ +#if BBGE_BUILD_SHADERS + if(!g_programObj) + return; + GLint loc = glGetUniformLocationARB(g_programObj, name); + if(loc != -1) + glUniform4fARB(loc, x, y, z, w); + else + shaderUniformError("setFloat4", name); +#endif +} diff --git a/BBGE/Shader.h b/BBGE/Shader.h index 1eb4cd9..0586272 100644 --- a/BBGE/Shader.h +++ b/BBGE/Shader.h @@ -30,28 +30,30 @@ public: ~Shader(); bool isLoaded(); 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; + + // TODO: design a good API for this... + void setInt(const char *name, int x); + void setFloat(const char *name, float x); + void setFloat4(const char *name, float x, float y, float z, float w); + + 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; #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); }; #endif From 2ac3ad9fb1ff005cf6b48023e3d0238d3d9cae5f Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sun, 12 May 2013 00:05:57 +0200 Subject: [PATCH 17/50] Fixes & enhancements to shader interface code --- BBGE/ScriptObject.cpp | 1 + BBGE/ScriptObject.h | 1 + BBGE/Shader.cpp | 193 ++++++++++++++++++++++++++++---------- BBGE/Shader.h | 48 ++++++++-- ExternalLibs/algorithmx.h | 34 +++++++ 5 files changed, 221 insertions(+), 56 deletions(-) create mode 100644 ExternalLibs/algorithmx.h diff --git a/BBGE/ScriptObject.cpp b/BBGE/ScriptObject.cpp index 442797b..60b5d01 100644 --- a/BBGE/ScriptObject.cpp +++ b/BBGE/ScriptObject.cpp @@ -38,6 +38,7 @@ static const char *scriptObjTypeNames[] = /* (1 <<10) */ "Quad", /* (1 <<11) */ "Text", /* (1 <<12) */ "PauseQuad", + /* (1 <<13) */ "Shader", NULL }; diff --git a/BBGE/ScriptObject.h b/BBGE/ScriptObject.h index 4c2ff20..a6bbb0a 100644 --- a/BBGE/ScriptObject.h +++ b/BBGE/ScriptObject.h @@ -40,6 +40,7 @@ enum ScriptObjectType 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 99a2e7c..1c8f4a8 100644 --- a/BBGE/Shader.cpp +++ b/BBGE/Shader.cpp @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "Shader.h" +#include "algorithmx.h" #ifdef BBGE_BUILD_SHADERS // GL_ARB_shader_objects @@ -34,9 +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; - PFNGLUNIFORM1FARBPROC glUniform1fARB = 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; @@ -84,16 +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"); - glUniform1fARB = (PFNGLUNIFORM1FARBPROC)SDL_GL_GetProcAddress("glUniform1fARB"); + 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 || !glUniform1fARB ) + !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"); @@ -116,6 +131,10 @@ end: Shader::Shader() { + addType(SCO_SHADER); + numUniforms = -1; + uniformsDirty = false; + #ifdef BBGE_BUILD_OPENGL g_programObj = 0; #endif @@ -139,7 +158,7 @@ void Shader::unload() #endif } -bool Shader::isLoaded() +bool Shader::isLoaded() const { return g_programObj != 0; } @@ -155,6 +174,7 @@ void Shader::bind() if (!_useShaders) return; glUseProgramObjectARB(g_programObj); + _flushUniforms(); #endif } @@ -217,6 +237,7 @@ void Shader::load(const std::string &file, const std::string &fragFile) void Shader::loadSrc(const char *vertCode, const char *fragCode) { + staticInit(); unload(); if(!_useShaders) @@ -232,7 +253,7 @@ void Shader::loadSrc(const char *vertCode, const char *fragCode) // // Create the vertex shader... // - if(vertCode && !(vertexShader = _compileShader(GL_VERTEX_SHADER_ARB, vertCode, str, sizeof(str)))) + if(vertCode && *vertCode && !(vertexShader = _compileShader(GL_VERTEX_SHADER_ARB, vertCode, str, sizeof(str)))) { std::ostringstream os; os << "Vertex Shader Compile Error [" << vertFile << "]:\n" << str; @@ -243,7 +264,7 @@ void Shader::loadSrc(const char *vertCode, const char *fragCode) // // Create the fragment shader... // - if(fragCode && !(fragmentShader = _compileShader(GL_FRAGMENT_SHADER_ARB, fragCode, str, sizeof(str)))) + if(fragCode && *fragCode && !(fragmentShader = _compileShader(GL_FRAGMENT_SHADER_ARB, fragCode, str, sizeof(str)))) { std::ostringstream os; os << "Fragment Shader Compile Error [" << fragFile << "]:\n" << str; @@ -294,59 +315,131 @@ void Shader::loadSrc(const char *vertCode, const char *fragCode) return; } + _queryUniforms(); + #endif } -// TODO: I'm not quite sure but i bet this sucks. -// Design a good caching policy and simplify the implementation, -// but keep shader dynamism and shaders generated at runtime in mind. -// No idea if and how much runtime performance it costs -// to query the uniform locations everytime. -// -- FG - -static void shaderUniformError(const char *func, const char *var) +void Shader::_setUniform(Uniform *u) { - GLint err = glGetError(); - /*std::ostringstream os; - os << "Shader::" << func << "(" << var << ") -- undef uniform (Error: " << err << ")"; - debugLog(os.str());*/ + /*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::setInt(const char *name, int x) +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); + 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) + if(!g_programObj || numUniforms <= 0) return; - GLint loc = glGetUniformLocationARB(g_programObj, name); - if(loc != -1) - glUniform1iARB(loc, x); - else - shaderUniformError("setInt", name); + 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) +void Shader::setFloat(const char *name, float x, float y /* = 0 */, float z /* = 0 */, float w /* = 0 */) { #if BBGE_BUILD_SHADERS - if(!g_programObj) + if(!g_programObj || numUniforms <= 0) return; - GLint loc = glGetUniformLocationARB(g_programObj, name); - if(loc != -1) - glUniform1fARB(loc, x); - else - shaderUniformError("setFloat", name); -#endif -} - -void Shader::setFloat4(const char *name, float x, float y, float z, float w) -{ -#if BBGE_BUILD_SHADERS - if(!g_programObj) - return; - GLint loc = glGetUniformLocationARB(g_programObj, name); - if(loc != -1) - glUniform4fARB(loc, x, y, z, w); - else - shaderUniformError("setFloat4", name); + 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 0586272..3d21050 100644 --- a/BBGE/Shader.h +++ b/BBGE/Shader.h @@ -22,13 +22,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define BBGE_SHADER_H #include "Base.h" +#include "ScriptObject.h" -class Shader +class Shader : public ScriptObject { 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(); @@ -36,16 +37,16 @@ public: void bind(); void unbind(); - // TODO: design a good API for this... - void setInt(const char *name, int x); - void setFloat(const char *name, float x); - void setFloat4(const char *name, float x, float y, float z, float w); + 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; + int numUniforms; #endif private: @@ -54,6 +55,41 @@ private: 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/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 From 8c80cf6318500adee6c64a1e707cc0422a4d15ad Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sun, 12 May 2013 00:06:26 +0200 Subject: [PATCH 18/50] Add shader interface API to Lua API --- Aquaria/ScriptInterface.cpp | 90 ++++++++++++++++++++++++++++++++++++- BBGE/AfterEffect.cpp | 12 +++++ BBGE/AfterEffect.h | 1 + 3 files changed, 102 insertions(+), 1 deletion(-) diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index d101194..c4517ea 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -361,7 +361,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)); @@ -378,6 +378,7 @@ void compile_time_assertions() compile_assert(oo(Path) == oo(Avatar)); compile_assert(oo(Path) == oo(BaseText)); compile_assert(oo(Path) == oo(PauseQuad)); + compile_assert(oo(Path) == oo(Shader)); #undef oo } #endif @@ -458,6 +459,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) { @@ -579,6 +586,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; @@ -7680,6 +7697,70 @@ luaFunc(text_setWidth) luaReturnNil(); } +luaFunc(loadShader) +{ + 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); + Shader *sh = new Shader(); + sh->load(vert, frag); + if(!sh->isLoaded()) + { + delete sh; + sh = NULL; + } + luaReturnPtr(sh); +} + +luaFunc(createShader) +{ + Shader *sh = new Shader(); + sh->loadSrc(getCString(L, 1), getCString(L, 2)); + if(!sh->isLoaded()) + { + delete sh; + sh = NULL; + } + luaReturnPtr(sh); +} + +luaFunc(shader_setAsAfterEffect) +{ + core->afterEffectManager->scriptShader = lua_isuserdata(L, 1) ? getShader(L, 1) : NULL; + luaReturnNil(); +} + +luaFunc(shader_setInt) +{ + Shader *sh = getShader(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) +{ + Shader *sh = getShader(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) +{ + Shader *sh = getShader(L); + delete sh; + if(core->afterEffectManager->scriptShader == sh) + core->afterEffectManager->scriptShader = NULL; + luaReturnNil(); +} + //-------------------------------------------------------------------------------------------- @@ -8550,6 +8631,13 @@ static const struct { luaRegister(text_setFontSize), luaRegister(text_setWidth), + luaRegister(loadShader), + luaRegister(createShader), + luaRegister(shader_setAsAfterEffect), + luaRegister(shader_setFloat), + luaRegister(shader_setInt), + luaRegister(shader_delete), + luaRegister(isQuad), luaRegister(isNode), luaRegister(isObject), diff --git a/BBGE/AfterEffect.cpp b/BBGE/AfterEffect.cpp index 2879cf8..5e7a091 100644 --- a/BBGE/AfterEffect.cpp +++ b/BBGE/AfterEffect.cpp @@ -35,6 +35,7 @@ AfterEffectManager::AfterEffectManager(int xDivs, int yDivs) activeShader = AS_NONE; numEffects = 0; bRenderGridPoints = true; + scriptShader = 0; screenWidth = core->getWindowWidth(); screenHeight = core->getWindowHeight(); @@ -245,6 +246,7 @@ void AfterEffectManager::setActiveShader(ActiveShader as) activeShader = as; } + void AfterEffectManager::renderGrid() { #ifdef BBGE_BUILD_OPENGL @@ -278,11 +280,21 @@ void AfterEffectManager::renderGrid() activeShader = &glowShader; break; } + + if(scriptShader) + activeShader = scriptShader; + } if (activeShader) + { + //while(glGetError() != GL_NO_ERROR) {} + activeShader->bind(); + activeShader->setInt("tex", 0); + } + screenWidth = core->getWindowWidth(); screenHeight = core->getWindowHeight(); diff --git a/BBGE/AfterEffect.h b/BBGE/AfterEffect.h index fd755d3..bfe70f7 100644 --- a/BBGE/AfterEffect.h +++ b/BBGE/AfterEffect.h @@ -125,6 +125,7 @@ public: int textureWidth, textureHeight; Shader blurShader, bwShader, washoutShader, motionBlurShader, glowShader; + Shader *scriptShader; Vector ** drawGrid; From 6666787f6d3f636e28329ca687b3aac9c63a0efe Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sun, 12 May 2013 00:06:38 +0200 Subject: [PATCH 19/50] vcproj update --- win/vc90/BBGE.vcproj | 4 ---- win/vc90/external.vcproj | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) 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}" > + + From cfd9b0ca5b0169b95323a1cd1591c6ef36b97fac Mon Sep 17 00:00:00 2001 From: fgenesis Date: Wed, 15 May 2013 01:56:50 +0200 Subject: [PATCH 20/50] Fix bug in shader uniform assignment --- BBGE/Shader.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/BBGE/Shader.cpp b/BBGE/Shader.cpp index 1c8f4a8..d29707e 100644 --- a/BBGE/Shader.cpp +++ b/BBGE/Shader.cpp @@ -405,6 +405,9 @@ 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()); } From 57171492341a69ca0e6ec3792bc7a58a9a3fee03 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Thu, 16 May 2013 01:55:10 +0200 Subject: [PATCH 21/50] Enable shaders for CMake build --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c16bd0..567f696 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -219,7 +219,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) From 36247593d4fc568dd2a56f8923fb9800ead4b769 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Thu, 16 May 2013 03:54:20 +0200 Subject: [PATCH 22/50] Fix possible crash due to unsafe shot iteration. Fixes regression introduced in 0784d1b9dff. With a std::list it was okay to create shots while iterating with an iterator, but not so with a std::vector. Now using index access, which is safe with push_back() operations. --- Aquaria/Game.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Aquaria/Game.cpp b/Aquaria/Game.cpp index 733399b..1f44e86 100644 --- a/Aquaria/Game.cpp +++ b/Aquaria/Game.cpp @@ -8402,9 +8402,9 @@ void Game::handleShotCollisions(Entity *e, bool hasShield) { BBGE_PROF(Game_handleShotCollisions); bool isRegValid=true; - for (Shot::Shots::iterator i = Shot::shots.begin(); i != Shot::shots.end(); i++) + for (size_t i = 0; i < Shot::shots.size(); ++i) { - Shot *shot = *i; + Shot *shot = Shot::shots[i]; if (shot->isActive() && isEntityCollideWithShot(e, shot) && (!hasShield || (!shot->shotData || !shot->shotData->ignoreShield))) { Vector collidePoint = e->position+e->offset; @@ -8434,9 +8434,9 @@ bool Game::isDamageTypeEnemy(DamageType dt) void Game::handleShotCollisionsSkeletal(Entity *e) { BBGE_PROF(Game_HSSKELETAL); - for (Shot::Shots::iterator i = Shot::shots.begin(); i != Shot::shots.end(); i++) + for (size_t i = 0; i < Shot::shots.size(); ++i) { - Shot *shot = *i; + Shot *shot = Shot::shots[i]; if (shot->isActive() && isEntityCollideWithShot(e, shot)) { Bone *b = collideSkeletalVsCircle(e, shot->position, shot->collideRadius); @@ -8451,9 +8451,9 @@ void Game::handleShotCollisionsSkeletal(Entity *e) void Game::handleShotCollisionsHair(Entity *e, int num) { - for (Shot::Shots::iterator i = Shot::shots.begin(); i != Shot::shots.end(); i++) + for (size_t i = 0; i < Shot::shots.size(); ++i) { - Shot *shot = *i; + Shot *shot = Shot::shots[i]; if (shot->isActive() && isEntityCollideWithShot(e, shot)) { bool b = collideHairVsCircle(e, num, shot->position, 8); From f7740eb6e8f163e9ce748c7ba4b543a321cb65c8 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sun, 19 May 2013 20:14:00 +0200 Subject: [PATCH 23/50] add beam_setDamageType() Lua function --- Aquaria/ScriptInterface.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index c4517ea..5f53ff2 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -3746,6 +3746,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); @@ -7950,6 +7960,7 @@ static const struct { luaRegister(beam_setDamage), luaRegister(beam_setBeamWidth), luaRegister(beam_setFirer), + luaRegister(beam_setDamageType), luaRegister(getStringBank), From 0611568d3efc7aead1ca3edc13d0f1f88b3ce388 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Fri, 24 May 2013 03:34:10 +0200 Subject: [PATCH 24/50] Add precacher for mods --- Aquaria/DSQ.cpp | 2 ++ Aquaria/DSQ.h | 2 ++ Aquaria/Mod.cpp | 22 ++++++++++++++++++++++ BBGE/Precacher.cpp | 13 ++++++++++--- BBGE/Precacher.h | 2 ++ 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/Aquaria/DSQ.cpp b/Aquaria/DSQ.cpp index 99427b2..dca1cc4 100644 --- a/Aquaria/DSQ.cpp +++ b/Aquaria/DSQ.cpp @@ -2334,6 +2334,8 @@ void DSQ::playPositionalSfx(const std::string &name, const Vector &position, flo void DSQ::shutdown() { + mod.stop(); + Network::shutdown(); scriptInterface.shutdown(); diff --git a/Aquaria/DSQ.h b/Aquaria/DSQ.h index e24d4ff..3be5ae6 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 diff --git a/Aquaria/Mod.cpp b/Aquaria/Mod.cpp index beac053..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() 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 From 1ea1408ac48009c3e94334139bdfc217d15ec541 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Fri, 24 May 2013 03:36:50 +0200 Subject: [PATCH 25/50] Animation editor enhancement. New key combo: Pressing Ctrl+Shift while moving/rotating a bone will move/rotate it globally, for all keys in all animations. --- Aquaria/AnimationEditor.cpp | 57 ++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 10 deletions(-) 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; + } + } } } } From f5f890aade8c5371e43c4543df03babb5adc052f Mon Sep 17 00:00:00 2001 From: fgenesis Date: Mon, 10 Jun 2013 00:59:46 +0200 Subject: [PATCH 26/50] Make particle suck positions accessible to Lua, use suckpos 2, fix possible crash in entity_clearHair() --- Aquaria/Avatar.cpp | 10 ++++++---- Aquaria/ScriptInterface.cpp | 26 +++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/Aquaria/Avatar.cpp b/Aquaria/Avatar.cpp index dd2cb05..e4b8bad 100644 --- a/Aquaria/Avatar.cpp +++ b/Aquaria/Avatar.cpp @@ -2158,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++) @@ -2189,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); } /* @@ -2202,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); } } @@ -2222,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()) diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index 5f53ff2..12ada91 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -3021,6 +3021,27 @@ luaFunc(spawnParticleEffect) luaReturnPtr(pe); } +luaFunc(setNumSuckPositions) +{ + particleManager->setNumSuckPositions(lua_tointeger(L, 0)); + luaReturnNil(); +} + +luaFunc(setSuckPosition) +{ + particleManager->setSuckPosition(lua_tointeger(L, 0), Vector(lua_tonumber(L, 1), lua_tonumber(L, 2))); + luaReturnNil(); +} + +luaFunc(getSuckPosition) +{ + Vector *v = particleManager->getSuckPosition(lua_tointeger(L, 0)); + if(v) + luaReturnVec2(v->x, v->y); + luaReturnVec2(0.0f, 0.0f); +} + + luaFunc(bone_showFrame) { Bone *b = bone(L); @@ -6958,7 +6979,7 @@ luaFunc(entity_getHair) luaFunc(entity_clearHair) { Entity *e = entity(L); - if (e) + if (e && e->hair) { e->hair->safeKill(); e->hair = 0; @@ -8157,6 +8178,9 @@ static const struct { luaRegister(resetTimer), luaRegister(addInfluence), + luaRegister(setSuckPosition), + luaRegister(setSuckPosition); + luaRegister(setNumSuckPositions), luaRegister(setupBasicEntity), luaRegister(playMusic), luaRegister(playMusicStraight), From 336c821eb2c42380cd99d5b189674b7710c66562 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Mon, 10 Jun 2013 01:02:47 +0200 Subject: [PATCH 27/50] Thou shall not push without compiling. --- Aquaria/ScriptInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index 12ada91..9d06c79 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -8179,7 +8179,7 @@ static const struct { luaRegister(addInfluence), luaRegister(setSuckPosition), - luaRegister(setSuckPosition); + luaRegister(setSuckPosition), luaRegister(setNumSuckPositions), luaRegister(setupBasicEntity), luaRegister(playMusic), From dcc676afbc61e66b6664cf86d14967e0d95e8601 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Mon, 10 Jun 2013 01:20:50 +0200 Subject: [PATCH 28/50] ... AND THOU SHALL TEST YOUR CODE BEFORE PUSH --- Aquaria/ScriptInterface.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index 9d06c79..77e312a 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -3023,19 +3023,19 @@ luaFunc(spawnParticleEffect) luaFunc(setNumSuckPositions) { - particleManager->setNumSuckPositions(lua_tointeger(L, 0)); + particleManager->setNumSuckPositions(lua_tointeger(L, 1)); luaReturnNil(); } luaFunc(setSuckPosition) { - particleManager->setSuckPosition(lua_tointeger(L, 0), Vector(lua_tonumber(L, 1), lua_tonumber(L, 2))); + 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, 0)); + Vector *v = particleManager->getSuckPosition(lua_tointeger(L, 1)); if(v) luaReturnVec2(v->x, v->y); luaReturnVec2(0.0f, 0.0f); From c698b4128a778263424c40d218952796d4e781b3 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Tue, 11 Jun 2013 09:02:56 +0200 Subject: [PATCH 29/50] Fix copypaste mistake in avatar_canLockToWall() & avatar_setCanLockToWall(). Add functions: - obj_getAlphaMod() - obj_getColor() --- Aquaria/ScriptInterface.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index 77e312a..f21ded2 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -865,6 +865,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); @@ -883,6 +889,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); @@ -1535,7 +1551,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 ) \ @@ -2761,13 +2779,13 @@ luaFunc(avatar_canBurst) luaFunc(avatar_setCanLockToWall) { - dsq->game->avatar->setCanBurst(getBool(L, 1)); + dsq->game->avatar->setCanLockToWall(getBool(L, 1)); luaReturnNil(); } luaFunc(avatar_canLockToWall) { - luaReturnBool(dsq->game->avatar->canBurst()); + luaReturnBool(dsq->game->avatar->canLockToWall()); } luaFunc(avatar_setCanSwimAgainstCurrents) From 3485199bec073aafcde759b3dc42189afae699f6 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sat, 15 Jun 2013 00:58:32 +0200 Subject: [PATCH 30/50] temp commit - work on shaders --- Aquaria/Avatar.cpp | 32 ------- Aquaria/Game.cpp | 5 - Aquaria/ScriptInterface.cpp | 12 ++- Aquaria/UserSettings.cpp | 8 -- Aquaria/UserSettings.h | 2 - BBGE/AfterEffect.cpp | 186 +++++++++++++----------------------- BBGE/AfterEffect.h | 22 +---- 7 files changed, 75 insertions(+), 192 deletions(-) diff --git a/Aquaria/Avatar.cpp b/Aquaria/Avatar.cpp index e4b8bad..1abb763 100644 --- a/Aquaria/Avatar.cpp +++ b/Aquaria/Avatar.cpp @@ -5742,38 +5742,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") diff --git a/Aquaria/Game.cpp b/Aquaria/Game.cpp index 1f44e86..5f2de4e 100644 --- a/Aquaria/Game.cpp +++ b/Aquaria/Game.cpp @@ -10719,11 +10719,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/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index f21ded2..0987607 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -3995,6 +3995,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); @@ -7779,7 +7781,9 @@ luaFunc(createShader) luaFunc(shader_setAsAfterEffect) { - core->afterEffectManager->scriptShader = lua_isuserdata(L, 1) ? getShader(L, 1) : NULL; + int idx = lua_tointeger(L, 2); + if(idx < core->afterEffectManager->scriptShader.size()) + core->afterEffectManager->scriptShader[idx] = lua_isuserdata(L, 1) ? getShader(L, 1) : NULL; luaReturnNil(); } @@ -7805,8 +7809,10 @@ luaFunc(shader_delete) { Shader *sh = getShader(L); delete sh; - if(core->afterEffectManager->scriptShader == sh) - core->afterEffectManager->scriptShader = NULL; + size_t sz = core->afterEffectManager->scriptShader.size(); + for(size_t i = 0; i < sz; ++i) + if(core->afterEffectManager->scriptShader[i] == sh) + core->afterEffectManager->scriptShader[i] = NULL; luaReturnNil(); } 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/BBGE/AfterEffect.cpp b/BBGE/AfterEffect.cpp index 5e7a091..474c22c 100644 --- a/BBGE/AfterEffect.cpp +++ b/BBGE/AfterEffect.cpp @@ -32,10 +32,9 @@ Effect::Effect() AfterEffectManager::AfterEffectManager(int xDivs, int yDivs) { active = false; - activeShader = AS_NONE; numEffects = 0; bRenderGridPoints = true; - scriptShader = 0; + scriptShader.resize(10, 0); screenWidth = core->getWindowWidth(); screenHeight = core->getWindowHeight(); @@ -44,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) { @@ -99,14 +63,6 @@ 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"); - */ } AfterEffectManager::~AfterEffectManager() @@ -191,29 +147,6 @@ 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() { #ifdef BBGE_BUILD_OPENGL @@ -225,7 +158,7 @@ void AfterEffectManager::render() 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); /* @@ -241,48 +174,33 @@ void AfterEffectManager::render() #endif } -void AfterEffectManager::setActiveShader(ActiveShader as) -{ - activeShader = as; -} - - void AfterEffectManager::renderGrid() { #ifdef BBGE_BUILD_OPENGL - //glBindTexture(GL_TEXTURE_2D, texture); + + + int shadersOn = 0; + int firstShader = -1; + int lastShader = -1; + for (size_t i = 0; i < scriptShader.size(); ++i) + { + if(scriptShader[i]) + { + ++shadersOn; + if(firstShader < 0) + firstShader = i; + lastShader = i; + } + } + if (core->frameBuffer.isInited()) core->frameBuffer.bindTexture(); - else - glBindTexture(GL_TEXTURE_2D, texture); - - - //bwShader.bind(); Shader *activeShader=0; if (core->frameBuffer.isInited()) { - switch(this->activeShader) - { - 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(scriptShader) - activeShader = scriptShader; + if(scriptShader.size() && scriptShader[0]) + activeShader = scriptShader[0]; } @@ -359,6 +277,40 @@ void AfterEffectManager::renderGrid() } } + if (activeShader) + activeShader->unbind(); + + float width2 = float(vw)/2; + float height2 = float(vh)/2; + + /* + for(size_t i = 1; i < scriptShader.size(); ++i) + { + if(scriptShader[i]) + { + if (core->frameBuffer.isInited()) + core->frameBuffer.startCapture(); + + scriptShader[i]->bind(); + scriptShader[i]->setInt("tex", 0); + glBegin(GL_QUADS); + glTexCoord2d(0.0f, 0.0f); + glVertex3f(-width2, height2, 0.0f); + glTexCoord2d(percentX, 0.0f); + glVertex3f( width2, height2, 0.0f); + glTexCoord2d(percentX, percentY); + glVertex3f( width2, -height2, 0.0f); + glTexCoord2d(0.0f, percentY); + glVertex3f(-width2, -height2, 0.0f); + glEnd(); + scriptShader[i]->unbind(); + + capture(); + } + } + */ + + // uncomment to render grid points /* glBindTexture(GL_TEXTURE_2D, 0); @@ -394,9 +346,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); @@ -427,8 +376,7 @@ void AfterEffectManager::renderGridPoints() void AfterEffectManager::unloadDevice() { - if (texture) - glDeleteTextures(1,&texture); + backupBuffer.unloadDevice(); } void AfterEffectManager::reloadDevice() @@ -443,22 +391,16 @@ 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); } void AfterEffectManager::addEffect(Effect *e) diff --git a/BBGE/AfterEffect.h b/BBGE/AfterEffect.h index bfe70f7..c43a11d 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,7 +86,6 @@ public: void resetGrid(); - void capture(); void render(); void renderGrid(); void renderGridPoints(); @@ -111,12 +100,6 @@ public: bool active; - void setActiveShader(ActiveShader as); - -#ifdef BBGE_BUILD_OPENGL - GLuint texture; -#endif - bool bRenderGridPoints; int numEffects; @@ -124,12 +107,11 @@ public: int screenWidth, screenHeight; int textureWidth, textureHeight; - Shader blurShader, bwShader, washoutShader, motionBlurShader, glowShader; - Shader *scriptShader; + std::vector scriptShader; Vector ** drawGrid; - ActiveShader activeShader; + FrameBuffer backupBuffer; }; From 836de140936f1140255e0e86147e4a6800fe0446 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sat, 15 Jun 2013 02:38:49 +0200 Subject: [PATCH 31/50] Implement multi-pass postprocessing shader. This allows attaching multiple shader programs, processing the entire screen as texture. Chaining shaders works, each shader will use the output of the previous shader as input. --- BBGE/AfterEffect.cpp | 161 +++++++++++++++++++++++-------------------- BBGE/AfterEffect.h | 1 + BBGE/Shader.cpp | 7 ++ 3 files changed, 96 insertions(+), 73 deletions(-) diff --git a/BBGE/AfterEffect.cpp b/BBGE/AfterEffect.cpp index 474c22c..85f5cc8 100644 --- a/BBGE/AfterEffect.cpp +++ b/BBGE/AfterEffect.cpp @@ -63,6 +63,28 @@ AfterEffectManager::AfterEffectManager(int xDivs, int yDivs) void AfterEffectManager::loadShaders() { + deleteShaders(); + + Shader *sh = new Shader(); + sh->load("data/shaders/test.vert", "data/shaders/test.frag"); + if(sh->isLoaded()) + scriptShader[0] = sh; + else + delete sh; + + sh = new Shader(); + sh->load("data/shaders/test2.vert", "data/shaders/test2.frag"); + if(sh->isLoaded()) + scriptShader[1] = sh; + else + delete sh; + + sh = new Shader(); + sh->load("data/shaders/test3.vert", "data/shaders/test3.frag"); + if(sh->isLoaded()) + scriptShader[2] = sh; + else + delete sh; } AfterEffectManager::~AfterEffectManager() @@ -77,6 +99,7 @@ AfterEffectManager::~AfterEffectManager() delete[] drawGrid; } deleteEffects(); + deleteShaders(); } void AfterEffectManager::deleteEffects() @@ -94,6 +117,18 @@ void AfterEffectManager::deleteEffects() openSpots.pop(); } +void AfterEffectManager::deleteShaders() +{ + for(size_t i = 0; i < scriptShader.size(); ++i) + { + if(scriptShader[i]) + { + delete scriptShader[i]; + scriptShader[i] = 0; + } + } +} + void AfterEffectManager::clear() { deleteEffects(); @@ -149,24 +184,18 @@ void AfterEffectManager::destroyEffect(int id) 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); 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(); @@ -178,78 +207,45 @@ void AfterEffectManager::renderGrid() { #ifdef BBGE_BUILD_OPENGL - - int shadersOn = 0; int firstShader = -1; int lastShader = -1; + Shader *activeShader = 0; for (size_t i = 0; i < scriptShader.size(); ++i) { if(scriptShader[i]) { - ++shadersOn; if(firstShader < 0) + { firstShader = i; + activeShader = scriptShader[i]; + } lastShader = i; } } - if (core->frameBuffer.isInited()) - core->frameBuffer.bindTexture(); - - Shader *activeShader=0; - if (core->frameBuffer.isInited()) - { - if(scriptShader.size() && scriptShader[0]) - activeShader = scriptShader[0]; - - } - - if (activeShader) - { - //while(glGetError() != GL_NO_ERROR) {} - - activeShader->bind(); - - activeShader->setInt("tex", 0); - } - 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++) { @@ -283,32 +279,48 @@ void AfterEffectManager::renderGrid() float width2 = float(vw)/2; float height2 = float(vh)/2; - /* - for(size_t i = 1; i < scriptShader.size(); ++i) + + if(firstShader != lastShader) { - if(scriptShader[i]) + // 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) { - if (core->frameBuffer.isInited()) - core->frameBuffer.startCapture(); + activeShader = scriptShader[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); - scriptShader[i]->bind(); - scriptShader[i]->setInt("tex", 0); + // note that offx, offy are negative here! glBegin(GL_QUADS); glTexCoord2d(0.0f, 0.0f); - glVertex3f(-width2, height2, 0.0f); + glVertex3f(offx, vh+offy, 0.0f); glTexCoord2d(percentX, 0.0f); - glVertex3f( width2, height2, 0.0f); + glVertex3f( vw+offx, vh+offy, 0.0f); glTexCoord2d(percentX, percentY); - glVertex3f( width2, -height2, 0.0f); + glVertex3f( vw+offx, offy, 0.0f); glTexCoord2d(0.0f, percentY); - glVertex3f(-width2, -height2, 0.0f); + glVertex3f(offx, offy, 0.0f); glEnd(); - scriptShader[i]->unbind(); - - capture(); + + activeShader->unbind(); } } - */ // uncomment to render grid points @@ -377,6 +389,7 @@ void AfterEffectManager::renderGridPoints() void AfterEffectManager::unloadDevice() { backupBuffer.unloadDevice(); + deleteShaders(); } void AfterEffectManager::reloadDevice() @@ -401,6 +414,8 @@ void AfterEffectManager::reloadDevice() backupBuffer.reloadDevice(); else backupBuffer.init(-1, -1, true); + + loadShaders(); } void AfterEffectManager::addEffect(Effect *e) diff --git a/BBGE/AfterEffect.h b/BBGE/AfterEffect.h index c43a11d..1de7063 100644 --- a/BBGE/AfterEffect.h +++ b/BBGE/AfterEffect.h @@ -91,6 +91,7 @@ public: void renderGridPoints(); void loadShaders(); + void deleteShaders(); void unloadDevice(); void reloadDevice(); diff --git a/BBGE/Shader.cpp b/BBGE/Shader.cpp index d29707e..faed2a3 100644 --- a/BBGE/Shader.cpp +++ b/BBGE/Shader.cpp @@ -192,6 +192,13 @@ unsigned int Shader::_compileShader(int type, const char *src, char *errbuf, siz #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); From 486e8f92ad4e29c0639b4d6ecf1a70ad8db1260a Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sat, 15 Jun 2013 03:00:20 +0200 Subject: [PATCH 32/50] Make the dark layer affected by postprocessing shaders. This has the side effect that elements on the dark layer will now properly wiggle when affected by water ripples. Before this patch, the dark layer was always drawn above the postprocessed screen content, unaffected. --- BBGE/Core.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/BBGE/Core.cpp b/BBGE/Core.cpp index 3bb0f1e..9f68f9f 100644 --- a/BBGE/Core.cpp +++ b/BBGE/Core.cpp @@ -3852,10 +3852,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) { @@ -3885,6 +3881,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) From 6962a3e3ab59c2f1b44519a5b10ce53097b0ed2d Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sat, 15 Jun 2013 04:11:11 +0200 Subject: [PATCH 33/50] Improvements to shader API; use handles instead of raw pointers. --- Aquaria/ScriptInterface.cpp | 75 ++++++++++++----------- BBGE/AfterEffect.cpp | 118 +++++++++++++++++++++++++++--------- BBGE/AfterEffect.h | 16 ++++- BBGE/Shader.cpp | 1 - BBGE/Shader.h | 2 +- 5 files changed, 145 insertions(+), 67 deletions(-) diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index 0987607..3c2b116 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -378,7 +378,6 @@ static void compile_time_assertions() compile_assert(oo(Path) == oo(Avatar)); compile_assert(oo(Path) == oo(BaseText)); compile_assert(oo(Path) == oo(PauseQuad)); - compile_assert(oo(Path) == oo(Shader)); #undef oo } #endif @@ -7750,6 +7749,7 @@ luaFunc(text_setWidth) luaFunc(loadShader) { + int handle = 0; const char *vertRaw = getCString(L, 1); const char *fragRaw = getCString(L, 2); std::string vert, frag; @@ -7757,62 +7757,68 @@ luaFunc(loadShader) findFile_helper(vertRaw, vert); if(fragRaw) findFile_helper(fragRaw, frag); - Shader *sh = new Shader(); - sh->load(vert, frag); - if(!sh->isLoaded()) - { - delete sh; - sh = NULL; - } - luaReturnPtr(sh); + + if(core->afterEffectManager) + handle = core->afterEffectManager->loadShaderFile(vert.c_str(), frag.c_str()); + + luaReturnInt(handle); } luaFunc(createShader) { - Shader *sh = new Shader(); - sh->loadSrc(getCString(L, 1), getCString(L, 2)); - if(!sh->isLoaded()) - { - delete sh; - sh = NULL; - } - luaReturnPtr(sh); + int handle = 0; + if(core->afterEffectManager) + handle = core->afterEffectManager->loadShaderSrc(getCString(L, 1), getCString(L, 2)); + luaReturnInt(handle); } luaFunc(shader_setAsAfterEffect) { - int idx = lua_tointeger(L, 2); - if(idx < core->afterEffectManager->scriptShader.size()) - core->afterEffectManager->scriptShader[idx] = lua_isuserdata(L, 1) ? getShader(L, 1) : NULL; + 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) { - Shader *sh = getShader(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)); + 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) { - Shader *sh = getShader(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)); + 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) { - Shader *sh = getShader(L); - delete sh; - size_t sz = core->afterEffectManager->scriptShader.size(); - for(size_t i = 0; i < sz; ++i) - if(core->afterEffectManager->scriptShader[i] == sh) - core->afterEffectManager->scriptShader[i] = NULL; + if(core->afterEffectManager) + core->afterEffectManager->unloadShader(lua_tointeger(L, 1)); luaReturnNil(); } @@ -8693,6 +8699,7 @@ static const struct { luaRegister(loadShader), luaRegister(createShader), luaRegister(shader_setAsAfterEffect), + luaRegister(shader_setNumAfterEffects), luaRegister(shader_setFloat), luaRegister(shader_setInt), luaRegister(shader_delete), diff --git a/BBGE/AfterEffect.cpp b/BBGE/AfterEffect.cpp index 85f5cc8..938d535 100644 --- a/BBGE/AfterEffect.cpp +++ b/BBGE/AfterEffect.cpp @@ -34,7 +34,7 @@ AfterEffectManager::AfterEffectManager(int xDivs, int yDivs) active = false; numEffects = 0; bRenderGridPoints = true; - scriptShader.resize(10, 0); + shaderPipeline.resize(10, 0); screenWidth = core->getWindowWidth(); screenHeight = core->getWindowHeight(); @@ -65,26 +65,7 @@ void AfterEffectManager::loadShaders() { deleteShaders(); - Shader *sh = new Shader(); - sh->load("data/shaders/test.vert", "data/shaders/test.frag"); - if(sh->isLoaded()) - scriptShader[0] = sh; - else - delete sh; - - sh = new Shader(); - sh->load("data/shaders/test2.vert", "data/shaders/test2.frag"); - if(sh->isLoaded()) - scriptShader[1] = sh; - else - delete sh; - - sh = new Shader(); - sh->load("data/shaders/test3.vert", "data/shaders/test3.frag"); - if(sh->isLoaded()) - scriptShader[2] = sh; - else - delete sh; + // ...Load shaders here... } AfterEffectManager::~AfterEffectManager() @@ -119,12 +100,15 @@ void AfterEffectManager::deleteEffects() void AfterEffectManager::deleteShaders() { - for(size_t i = 0; i < scriptShader.size(); ++i) + for(size_t i = 0; i < shaderPipeline.size(); ++i) + shaderPipeline[i] = 0; + + for(size_t i = 0; i < loadedShaders.size(); ++i) { - if(scriptShader[i]) + if(loadedShaders[i]) { - delete scriptShader[i]; - scriptShader[i] = 0; + delete loadedShaders[i]; + loadedShaders[i] = 0; } } } @@ -210,14 +194,14 @@ void AfterEffectManager::renderGrid() int firstShader = -1; int lastShader = -1; Shader *activeShader = 0; - for (size_t i = 0; i < scriptShader.size(); ++i) + for (size_t i = 0; i < shaderPipeline.size(); ++i) { - if(scriptShader[i]) + if(shaderPipeline[i]) { if(firstShader < 0) { firstShader = i; - activeShader = scriptShader[i]; + activeShader = shaderPipeline[i]; } lastShader = i; } @@ -290,7 +274,7 @@ void AfterEffectManager::renderGrid() for(int i = firstShader + 1; i <= lastShader; ++i) { - activeShader = scriptShader[i]; + activeShader = shaderPipeline[i]; if(!activeShader) continue; @@ -567,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 1de7063..90c7d9f 100644 --- a/BBGE/AfterEffect.h +++ b/BBGE/AfterEffect.h @@ -108,11 +108,23 @@ public: int screenWidth, screenHeight; int textureWidth, textureHeight; - std::vector scriptShader; + 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; + }; diff --git a/BBGE/Shader.cpp b/BBGE/Shader.cpp index faed2a3..c6468bc 100644 --- a/BBGE/Shader.cpp +++ b/BBGE/Shader.cpp @@ -131,7 +131,6 @@ end: Shader::Shader() { - addType(SCO_SHADER); numUniforms = -1; uniformsDirty = false; diff --git a/BBGE/Shader.h b/BBGE/Shader.h index 3d21050..2b978e7 100644 --- a/BBGE/Shader.h +++ b/BBGE/Shader.h @@ -24,7 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "Base.h" #include "ScriptObject.h" -class Shader : public ScriptObject +class Shader { public: Shader(); From 84a73b59f99f15b0ab009f7606f190f4394963ad Mon Sep 17 00:00:00 2001 From: fgenesis Date: Wed, 19 Jun 2013 02:26:12 +0200 Subject: [PATCH 34/50] Hopefully fixed piranha pet script warning (thx `Nax for reporting) --- game_scripts/scripts/entities/pet_piranha.lua | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) 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 From 61395779a1fbc4d94d889b088d36f648d2e83c91 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Wed, 19 Jun 2013 15:09:05 +0200 Subject: [PATCH 35/50] Do not try to load .zip files in _mods automatically. This has been a great source of confusion and it's better to remove it. --- Aquaria/DSQ.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Aquaria/DSQ.cpp b/Aquaria/DSQ.cpp index dca1cc4..31f1b97 100644 --- a/Aquaria/DSQ.cpp +++ b/Aquaria/DSQ.cpp @@ -2154,7 +2154,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); From 1bbd9e097dd0ba94fbc72f173f3e16ac71284d06 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Thu, 20 Jun 2013 04:49:20 +0200 Subject: [PATCH 36/50] Initial supported for scripted ingredients, not fully tested. This adds a few additional interface functions, to be defined in: scripts/global/cooking.lua, or _mods/XYZ/scripts/cooking.lua Added functions: cookFailure(a,b,c) - Called when no recipe could be found for ingredients a,b,c getIngredientString() - Called by the menu. Expected to return effects description for scripted ingredient.. useIngredient(name) - Called when a scripted ingredient will be eaten. Return true to eat. Use a line like this in ingredients.txt: LuaLoaf sealoaf Loaf (script) to enable calling useIngredient() upon eating. --- Aquaria/Continuity.cpp | 74 +++++++++++++++---- Aquaria/DSQ.h | 7 +- Aquaria/Game.cpp | 87 +++++++++------------- Aquaria/Game.h | 2 + Aquaria/Ingredient.cpp | 13 +--- Aquaria/SceneEditor.cpp | 8 +- Aquaria/ScriptInterface.cpp | 141 ++++++++++++++++++++++++++++++++++-- Aquaria/ScriptInterface.h | 6 ++ 8 files changed, 250 insertions(+), 88 deletions(-) diff --git a/Aquaria/Continuity.cpp b/Aquaria/Continuity.cpp index 18ee693..1a39f32 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,36 @@ 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); + } 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); } @@ -920,6 +931,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 +943,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); @@ -944,7 +961,7 @@ void Continuity::loadIngredientData(const std::string &file) if (p1 != std::string::npos && p2 != std::string::npos) { effects = effects.substr(p1+1, p2-(p1+1)); - std::istringstream fxLine(effects); + SimpleIStringStream fxLine(effects.c_str(), SimpleIStringStream::REUSE); std::string bit; while (fxLine >> bit) { @@ -1032,6 +1049,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 +1073,31 @@ void Continuity::loadIngredientData(const std::string &file) ingredientData.push_back(data); } + if(extradata) + { + while (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; + continue; + } + 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; diff --git a/Aquaria/DSQ.h b/Aquaria/DSQ.h index 3be5ae6..b4df465 100644 --- a/Aquaria/DSQ.h +++ b/Aquaria/DSQ.h @@ -685,6 +685,7 @@ enum IngredientEffectType IET_POISON = 17, IET_BLIND = 18, IET_ALLSTATUS = 19, + IET_SCRIPT = 20, IET_MAX }; @@ -715,9 +716,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; @@ -1051,7 +1054,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 @@ -1059,7 +1062,7 @@ public: IngredientData *getIngredientHeldByIndex(int idx) const; IngredientData *getIngredientDataByIndex(int idx); - void applyIngredientEffects(IngredientData *data); + bool applyIngredientEffects(IngredientData *data); void loadIngredientData(const std::string &file); void loadIngredientDisplayNames(const std::string& file); diff --git a/Aquaria/Game.cpp b/Aquaria/Game.cpp index 5f2de4e..6e2ddfd 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 @@ -1236,6 +1234,8 @@ Game::Game() : StateObject() lastCollideMaskIndex = -1; worldPaused = false; + cookingScript = 0; + } Game::~Game() @@ -5836,41 +5836,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++) @@ -5994,7 +5959,6 @@ void Game::action(int id, int state) if (foodSlots[i]->isCursorIn() && foodSlots[i]->getIngredient()) { foodSlots[i]->moveRight(); - adjustFoodSlotCursor(); break; } } @@ -6031,7 +5995,6 @@ void Game::action(int id, int state) if (ingrIndex >= 0) { foodSlots[ingrIndex]->discard(); - adjustFoodSlotCursor(); } } } @@ -6709,6 +6672,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 /* @@ -7244,7 +7215,20 @@ 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; + 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"); @@ -7424,6 +7408,8 @@ void Game::onCook() } refreshFoodSlots(true); +endcook: + AquariaGuiElement::canDirMoveGlobal = true; isCooking = false; @@ -8740,7 +8726,6 @@ void Game::refreshFoodSlots(bool effects) { foodSlots[i]->refresh(effects); } - adjustFoodSlotCursor(); } void Game::refreshTreasureSlots() diff --git a/Aquaria/Game.h b/Aquaria/Game.h index d9c103e..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; diff --git a/Aquaria/Ingredient.cpp b/Aquaria/Ingredient.cpp index 97b9e42..f5b759d 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() 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 3c2b116..a9652de 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 }; @@ -2997,11 +3000,6 @@ luaFunc(entity_followPath) luaReturnNil(); } -luaFunc(getIngredientGfx) -{ - luaReturnStr(dsq->continuity.getIngredientGfx(getString(L, 1)).c_str()); -} - luaFunc(spawnIngredient) { int times = lua_tonumber(L, 4); @@ -6728,6 +6726,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); @@ -7704,6 +7709,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)); @@ -7876,6 +7957,7 @@ static const struct { luaRegister(reconstructEntityGrid), luaRegister(ing_hasIET), + luaRegister(ing_getIngredientName), luaRegister(esetv), luaRegister(esetvf), @@ -8196,8 +8278,6 @@ static const struct { luaRegister(registerSporeDrop), - luaRegister(getIngredientGfx), - luaRegister(spawnIngredient), luaRegister(spawnAllIngredients), luaRegister(spawnParticleEffect), @@ -8690,6 +8770,17 @@ 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), @@ -8746,6 +8837,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}, @@ -9972,6 +10064,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); From 25727244ad2437ebf424c983f6f04ef4789c45cb Mon Sep 17 00:00:00 2001 From: fgenesis Date: Thu, 20 Jun 2013 05:15:07 +0200 Subject: [PATCH 37/50] Little correction to prev commit Only handle cooking failure if the function call was successful. Otherwise, fallback to SeaLoaf. --- Aquaria/Game.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Aquaria/Game.cpp b/Aquaria/Game.cpp index 6e2ddfd..3270fbc 100644 --- a/Aquaria/Game.cpp +++ b/Aquaria/Game.cpp @@ -7221,11 +7221,13 @@ void Game::onCook() const char *p2 = cookList[1]->name.c_str(); const char *p3 = cookList.size() >= 3 ? cookList[2]->name.c_str() : ""; std::string ingname; - cookingScript->call("cookFailure", p1, p2, p3, &ingname); - if(ingname.length()) - data = dsq->continuity.getIngredientDataByName(ingname); - if(!data) - goto endcook; + if(cookingScript->call("cookFailure", p1, p2, p3, &ingname)) + { + if(ingname.length()) + data = dsq->continuity.getIngredientDataByName(ingname); + if(!data) + goto endcook; + } } if(!data) From 54d609a8b507ddcab2127b88735e70adf07c1091 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Thu, 20 Jun 2013 20:01:51 +0200 Subject: [PATCH 38/50] Make avatar respect maxspeed lerp, allow changing speed multiplier via script. Some extra functions. Add one additional not-timed speed multiplier that also ignores influence by currents. Lua functions added: - avatar_setSpeedMult(num, time) - avatar_setSpeedMult2(num) - avatar_getSpeedMult() - avatar_getSpeedMult2() - entity_isInCurrent(entity) - entity_getNumTargetPoints(entity) --- Aquaria/Avatar.cpp | 10 +++------- Aquaria/Continuity.cpp | 1 + Aquaria/DSQ.h | 2 ++ Aquaria/ScriptInterface.cpp | 40 +++++++++++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 7 deletions(-) diff --git a/Aquaria/Avatar.cpp b/Aquaria/Avatar.cpp index 1abb763..c597fd4 100644 --- a/Aquaria/Avatar.cpp +++ b/Aquaria/Avatar.cpp @@ -4911,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) diff --git a/Aquaria/Continuity.cpp b/Aquaria/Continuity.cpp index 1a39f32..ed509af 100644 --- a/Aquaria/Continuity.cpp +++ b/Aquaria/Continuity.cpp @@ -3209,6 +3209,7 @@ void Continuity::reset() //worldMapTiles.clear(); speedMult = biteMult = fishPoison = defenseMult = 1; + speedMult2 = 1; poison = 0; energyMult = 0; light = petPower = 0; diff --git a/Aquaria/DSQ.h b/Aquaria/DSQ.h index b4df465..777a11b 100644 --- a/Aquaria/DSQ.h +++ b/Aquaria/DSQ.h @@ -1102,6 +1102,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/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index a9652de..856f1fb 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -2898,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)); @@ -3208,6 +3230,11 @@ luaFunc(entity_checkSplash) luaReturnBool(ret); } +luaFunc(entity_isInCurrent) +{ + Entity *e = entity(L); + luaReturnBool(e ? e->isInCurrent() : false); +} luaFunc(entity_isUnderWater) { @@ -5609,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; @@ -8066,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), @@ -8453,6 +8488,11 @@ static const struct { luaRegister(avatar_setBlockSinging), luaRegister(avatar_isBlockSinging), + luaRegister(avatar_setSpeedMult), + luaRegister(avatar_setSpeedMult2), + luaRegister(avatar_getSpeedMult), + luaRegister(avatar_getSpeedMult2), + luaRegister(avatar_toggleMovement), From 416b521a12c935d27db2c9fe9904bece5a11533a Mon Sep 17 00:00:00 2001 From: fgenesis Date: Thu, 20 Jun 2013 21:39:17 +0200 Subject: [PATCH 39/50] Initial support for loading android save files. Apparently there is a new map with the index 55 -- a related entry was added to the worldmap.txt file to prevent data loss, just in case. field is not yet handled missing. Hopefully the resulting format can be loaded on android without problems, especially because both "ingr" and "ingrNames" fields appear in the StartData tag now. --- Aquaria/Continuity.cpp | 37 ++++++++++++++++++++++++++- files/data/worldmap.txt | 56 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 files/data/worldmap.txt diff --git a/Aquaria/Continuity.cpp b/Aquaria/Continuity.cpp index ed509af..87514f2 100644 --- a/Aquaria/Continuity.cpp +++ b/Aquaria/Continuity.cpp @@ -2461,6 +2461,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); + // ANDROID TODO: "ch" field startData.SetAttribute("naijaModel", dsq->continuity.naijaModel); startData.SetAttribute("costume", dsq->continuity.costume); startData.SetAttribute("form", dsq->continuity.form); @@ -2479,6 +2480,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++) { @@ -2551,6 +2562,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; @@ -2810,7 +2824,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; } @@ -2853,6 +2869,23 @@ void Continuity::loadFile(int slot) dsq->continuity.form = FormType(atoi(startData->Attribute("form"))); } + 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); + } + } + } + if (startData->Attribute("ingr")) { std::istringstream is(startData->Attribute("ingr")); @@ -2916,6 +2949,8 @@ void Continuity::loadFile(int slot) } } + // TODO ANDROID: "ch" field + if (startData->Attribute("h")) { int read = atoi(startData->Attribute("h")); diff --git a/files/data/worldmap.txt b/files/data/worldmap.txt new file mode 100644 index 0000000..089a59e --- /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 19 UNKNOWN 0 1 0 0 0 1 From fe5f6faa466d67525297456567cba1e68c8446d8 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Fri, 21 Jun 2013 00:40:19 +0200 Subject: [PATCH 40/50] More save data compat with android version (world map gem data) --- Aquaria/Continuity.cpp | 81 ++++++++++++++++++++++++++++++++++++++---- Aquaria/DSQ.h | 1 + 2 files changed, 75 insertions(+), 7 deletions(-) diff --git a/Aquaria/Continuity.cpp b/Aquaria/Continuity.cpp index 87514f2..8cff2f3 100644 --- a/Aquaria/Continuity.cpp +++ b/Aquaria/Continuity.cpp @@ -2356,15 +2356,32 @@ 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); @@ -2748,6 +2765,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"); @@ -2785,6 +2803,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()); @@ -3134,6 +3200,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 diff --git a/Aquaria/DSQ.h b/Aquaria/DSQ.h index 777a11b..3886e1d 100644 --- a/Aquaria/DSQ.h +++ b/Aquaria/DSQ.h @@ -618,6 +618,7 @@ struct GemData GemData() { canMove=false; } std::string name; std::string userString; + std::string mapName; bool canMove; Vector pos; }; From 46516eefc8594f35f57c561e2f8841bb27f7cc64 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Fri, 21 Jun 2013 00:41:07 +0200 Subject: [PATCH 41/50] ooops --- Aquaria/Continuity.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Aquaria/Continuity.cpp b/Aquaria/Continuity.cpp index 8cff2f3..11a9e39 100644 --- a/Aquaria/Continuity.cpp +++ b/Aquaria/Continuity.cpp @@ -2361,6 +2361,7 @@ void Continuity::saveFile(int slot, Vector position, unsigned char *scrShotData, // 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() << " "; @@ -2381,6 +2382,7 @@ void Continuity::saveFile(int slot, Vector position, unsigned char *scrShotData, os << spacesToUnderscores((*i).userString) << " "; } gems.SetAttribute("d", os.str()); + */ } doc.InsertEndChild(gems); From 2c99f010a475ac17aecd7cacf994cc322fea6e78 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Fri, 21 Jun 2013 03:33:35 +0200 Subject: [PATCH 42/50] Fixes to scripted ingredients, now it actually works --- Aquaria/Continuity.cpp | 77 +++++++++++++++++++++++------------------- Aquaria/DSQ.cpp | 1 + Aquaria/DSQ.h | 1 + 3 files changed, 45 insertions(+), 34 deletions(-) diff --git a/Aquaria/Continuity.cpp b/Aquaria/Continuity.cpp index 11a9e39..3a1ed8c 100644 --- a/Aquaria/Continuity.cpp +++ b/Aquaria/Continuity.cpp @@ -850,6 +850,7 @@ bool Continuity::applyIngredientEffects(IngredientData *data) if(dsq->game->cookingScript) dsq->game->cookingScript->call("useIngredient", data->name.c_str(), &eaten); } + break; default: { char str[256]; @@ -921,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; @@ -961,7 +999,7 @@ void Continuity::loadIngredientData(const std::string &file) if (p1 != std::string::npos && p2 != std::string::npos) { effects = effects.substr(p1+1, p2-(p1+1)); - SimpleIStringStream fxLine(effects.c_str(), SimpleIStringStream::REUSE); + std::istringstream fxLine(effects); std::string bit; while (fxLine >> bit) { @@ -1075,7 +1113,7 @@ void Continuity::loadIngredientData(const std::string &file) if(extradata) { - while (in >> line) + while (std::getline(in, line)) { SimpleIStringStream inLine(line.c_str(), SimpleIStringStream::REUSE); int maxAmount = MAX_INGREDIENT_AMOUNT; @@ -1084,7 +1122,7 @@ void Continuity::loadIngredientData(const std::string &file) if (name == "==Recipes==") { recipes = true; - continue; + break; } IngredientData *data = getIngredientDataByName(name); if(!data) @@ -3343,40 +3381,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/DSQ.cpp b/Aquaria/DSQ.cpp index 31f1b97..cfa6aca 100644 --- a/Aquaria/DSQ.cpp +++ b/Aquaria/DSQ.cpp @@ -614,6 +614,7 @@ void DSQ::debugMenu() core->afterEffectManager->loadShaders(); } dsq->user.load(); + dsq->continuity.loadIngredientData(); } else if (c == '2') { diff --git a/Aquaria/DSQ.h b/Aquaria/DSQ.h index 3886e1d..b4a6461 100644 --- a/Aquaria/DSQ.h +++ b/Aquaria/DSQ.h @@ -1065,6 +1065,7 @@ public: bool applyIngredientEffects(IngredientData *data); + void loadIngredientData(); void loadIngredientData(const std::string &file); void loadIngredientDisplayNames(const std::string& file); bool hasIngredients() const { return !ingredients.empty(); } From 211eb80c0aad00f86647e8ac419ca02ceaa62da6 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sat, 22 Jun 2013 23:51:29 +0200 Subject: [PATCH 43/50] Fix typo setting ingredient rotKind default value to the opposite of what it should be --- Aquaria/Ingredient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Aquaria/Ingredient.cpp b/Aquaria/Ingredient.cpp index f5b759d..ef791f0 100644 --- a/Aquaria/Ingredient.cpp +++ b/Aquaria/Ingredient.cpp @@ -24,7 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. IngredientData::IngredientData(const std::string &name, const std::string &gfx, IngredientType type) : 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) +, rotKind(!(type == IT_OIL && type == IT_EGG)) { } From 7891a2f0113d8b9508bad01dd1b7e62e771862ab Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sun, 23 Jun 2013 02:53:47 +0200 Subject: [PATCH 44/50] Fix naija not moving properly on machines with very high FPS. This bug occured when standing still and attempting to move, having high FPS and very low difftime. With near-zero vel, it was not built up enough per frame, therefore velLen was always < 2 and was subsequently reset back to 0, which resulted in naija never actually moving. This bug could be reproduced by holding Shift+F with 60 FPS, and then holding an arrow key. Thanks to `Nax for reporting the problem. (Cleaned out some cruft too, the actual change is the last line of the diff) --- Aquaria/Avatar.cpp | 101 +-------------------------------------------- 1 file changed, 2 insertions(+), 99 deletions(-) diff --git a/Aquaria/Avatar.cpp b/Aquaria/Avatar.cpp index c597fd4..556b8da 100644 --- a/Aquaria/Avatar.cpp +++ b/Aquaria/Avatar.cpp @@ -6467,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; @@ -6481,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(); @@ -6507,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 @@ -6557,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) { @@ -6614,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(); @@ -6635,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; @@ -6664,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) @@ -6699,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 @@ -6739,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); } @@ -7074,7 +6977,7 @@ void Avatar::onUpdate(float dt) { /*collideCheck:*/ - if (vel.getLength2D() < sqr(2)) + if (!isSwimming() && vel.getLength2D() < sqr(2)) { vel = Vector(0,0,0); } From 2bc3882a69693c925846ccda39cca6b5b98f6fb6 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sun, 23 Jun 2013 03:15:55 +0200 Subject: [PATCH 45/50] Add missing map #55 to the world map: The whale. --- files/data/worldmap.txt | 2 +- files/gfx/gui/worldmap/whale.png | Bin 0 -> 2795 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 files/gfx/gui/worldmap/whale.png diff --git a/files/data/worldmap.txt b/files/data/worldmap.txt index 089a59e..f82cc39 100644 --- a/files/data/worldmap.txt +++ b/files/data/worldmap.txt @@ -53,4 +53,4 @@ 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 19 UNKNOWN 0 1 0 0 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 0000000000000000000000000000000000000000..016b8d1b9c4bda113e61b6937d511e85a4d30487 GIT binary patch literal 2795 zcmeAS@N?(olHy`uVBq!ia0y~yU}OMc4mJh`hM1xiX&_#4kh>GZx^prw85kH?(j9#r z85lP9bN@+XWnf@XNcITwWnidMV_;}#VPN>hz`)S(f`OsbfPvvv0t1893 zCA|M8(s#UA#oK5+kbszk^LMyZD7*)nkwAED&k0?G4_{$<^*i~RSe z^ya^qZNLBhs;zxv9{$PgUH5ORS5G(2i?4q3c1PLY%J}n#AJ5TPz~I+n{Uf*g^Xso% zdt-0D|D9t0siJ;ux#W6&xntAsUbmil|C;rb;_mFvKX&}uWAoJV=R9FnkprCt4h3yaa_SSkA{Ey>G*nc&*dR@4d`rpT)M|Tug z7TaH*{UcE1K;>ci@TFh3uAcn=qu;;Po{w!?KGq%i!P#NmviNi)qm1b9UH>a$cjefd zX2-qaWqQ1{NyuW;643*KYxULt?ReCGeev^szu)TANi_B!SF`$gk1OFmQ^fiok7Zwe zr>v|{{DLR&E4B?9=K-yXWpqt^Z!=vo1I&G z@AOBlhS`$hvp;T5ji0Xn;8cB0!Nz5dvG zjo*g%&u!hEZC=h$ZrrPVZc}f(#mC17@>4g|PB>n%_{(m29V5SMUsJDq3rv;gD?6z% zapL2y`tL@zx%{jf?&ofl+W&lit;4aNa<<1UHTCDR-+$bDecSum4;}nWH}~tDza7jt z=iPR(Lpz-Q&VSEyY-8`E;@7pmf_C0{AHwkbeA?ctch}`Seq|cB-tOu8!ln27j(67o z6WV#lJ%EAVeD>G9%^!c2|M~SnwLam*x2WnnXDuGe=Xu85Q`T-cKJ(!m-!+^1FUoct0=-7ICniezgAgjt{H66?>df48}I&9}1S zgM(OTvt-6E?{6?JZ(|xbIDB*#FsRAxb5>u#u!fOI zm|LTvv;F-AP7Q|ah66{KxDp;cv@T)dIv}NBu(5$@M#T@lxeZJk*oKX^FE3gDF& Date: Sun, 23 Jun 2013 03:18:23 +0200 Subject: [PATCH 46/50] Savefile: Use ingr only if ingrNames does not exist. Using ingrNames is a lot safer for changing ingredients.txt. --- Aquaria/Continuity.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Aquaria/Continuity.cpp b/Aquaria/Continuity.cpp index 3a1ed8c..a3c0e90 100644 --- a/Aquaria/Continuity.cpp +++ b/Aquaria/Continuity.cpp @@ -2991,8 +2991,7 @@ void Continuity::loadFile(int slot) } } } - - if (startData->Attribute("ingr")) + else if (startData->Attribute("ingr")) // use this only if ingrNames does not exist. { std::istringstream is(startData->Attribute("ingr")); int idx; From 7faee73f141518b216cb317209216997b48aa537 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sun, 23 Jun 2013 04:43:24 +0200 Subject: [PATCH 47/50] Android save compat: Support "ch" (current health) value, and make maxHealth float. --- Aquaria/Continuity.cpp | 21 +++++++++++++++++---- Aquaria/DSQ.h | 2 +- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Aquaria/Continuity.cpp b/Aquaria/Continuity.cpp index a3c0e90..71d0a6d 100644 --- a/Aquaria/Continuity.cpp +++ b/Aquaria/Continuity.cpp @@ -2518,7 +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); - // ANDROID TODO: "ch" field + startData.SetAttribute("ch", dsq->continuity.health); startData.SetAttribute("naijaModel", dsq->continuity.naijaModel); startData.SetAttribute("costume", dsq->continuity.costume); startData.SetAttribute("form", dsq->continuity.form); @@ -3054,11 +3054,9 @@ void Continuity::loadFile(int slot) } } - // TODO ANDROID: "ch" field - if (startData->Attribute("h")) { - int read = atoi(startData->Attribute("h")); + float read = strtof(startData->Attribute("h"), NULL); maxHealth = read; health = read; std::ostringstream os; @@ -3071,6 +3069,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")); diff --git a/Aquaria/DSQ.h b/Aquaria/DSQ.h index b4a6461..555b04d 100644 --- a/Aquaria/DSQ.h +++ b/Aquaria/DSQ.h @@ -951,7 +951,7 @@ public: std::string getSaveFileName(int slot, const std::string &pfix); - int maxHealth; + float maxHealth; float health; bool hudVisible; unsigned int exp; From 26d056d92450be7d4b1b40635a4f5534c6ecbf78 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sun, 23 Jun 2013 18:50:10 +0200 Subject: [PATCH 48/50] Slightly more sensible error/msgbox handling --- Aquaria/AquariaMenuItem.cpp | 11 +--------- Aquaria/Continuity.cpp | 2 +- Aquaria/DSQ.cpp | 11 +++++----- Aquaria/Game.cpp | 5 ++--- Aquaria/GameplayVariables.cpp | 3 +-- Aquaria/ScriptInterface.cpp | 4 ++-- Aquaria/StringBank.cpp | 3 +++ BBGE/Base.cpp | 33 ++++++++++++++--------------- BBGE/Base.h | 6 ++---- BBGE/Core.cpp | 40 +++++++++-------------------------- BBGE/Core.h | 2 -- BBGE/SkeletalSprite.cpp | 3 +-- BBGE/StateManager.cpp | 2 +- BBGE/Texture.cpp | 2 -- BBGE/Vector.cpp | 4 ++-- 15 files changed, 48 insertions(+), 83 deletions(-) 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/Continuity.cpp b/Aquaria/Continuity.cpp index 71d0a6d..3dcd985 100644 --- a/Aquaria/Continuity.cpp +++ b/Aquaria/Continuity.cpp @@ -2659,7 +2659,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 diff --git a/Aquaria/DSQ.cpp b/Aquaria/DSQ.cpp index cfa6aca..2d20ce1 100644 --- a/Aquaria/DSQ.cpp +++ b/Aquaria/DSQ.cpp @@ -922,12 +922,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 +999,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 +1042,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; } diff --git a/Aquaria/Game.cpp b/Aquaria/Game.cpp index 3270fbc..1520c8d 100644 --- a/Aquaria/Game.cpp +++ b/Aquaria/Game.cpp @@ -2432,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)) { @@ -5213,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 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/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index 856f1fb..cb51bf3 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -713,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) 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/BBGE/Base.cpp b/BBGE/Base.cpp index 6feee42..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; @@ -316,10 +315,10 @@ void drawCircle(float radius, int stepSize) #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/Core.cpp b/BBGE/Core.cpp index 9f68f9f..e1aa0d2 100644 --- a/BBGE/Core.cpp +++ b/BBGE/Core.cpp @@ -817,7 +817,7 @@ bool Core::getMetaState() void Core::errorLog(const std::string &s) { - messageBox("Message", s); + messageBox("Error!", s); debugLog(s); } @@ -827,16 +827,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) @@ -1267,7 +1258,7 @@ void Core::init() if((SDL_Init(0))==-1) { - exit(0); + exit_error("Failed to init SDL"); } #endif @@ -1910,16 +1901,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 } @@ -1943,9 +1933,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 @@ -1953,9 +1942,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 } @@ -2625,13 +2613,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; @@ -4847,14 +4828,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 8e45ab3..1c514c9 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; 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 e82aefb..eb3195a 100644 --- a/BBGE/StateManager.cpp +++ b/BBGE/StateManager.cpp @@ -288,7 +288,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) { From 7dca65351cec4524589497e960d1c7a6f9efbc86 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sun, 23 Jun 2013 22:28:46 +0200 Subject: [PATCH 49/50] Implement loading/saving some more state data. This is the final commit for android savegame compatibility. Thanks to Andrew Church for explaining the new attributes and their format. --- Aquaria/Avatar.h | 3 +- Aquaria/Continuity.cpp | 187 ++++++++++++++++++++++++++++++++++++++++- Aquaria/Web.cpp | 8 ++ Aquaria/Web.h | 1 + 4 files changed, 195 insertions(+), 4 deletions(-) diff --git a/Aquaria/Avatar.h b/Aquaria/Avatar.h index dea3095..0287a1d 100644 --- a/Aquaria/Avatar.h +++ b/Aquaria/Avatar.h @@ -345,6 +345,7 @@ public: SeeMapMode getSeeMapMode() const { return _seeMapMode; } int leaches; + float shieldPoints; protected: void setSongIconPositions(); @@ -385,8 +386,6 @@ protected: Vector fallGravity; int lastOutOfWaterMaxSpeed; - int shieldPoints; - void onIdle(); void onHeal(int type); ParticleEffect biteLeftEmitter, biteRightEmitter, swimEmitter, auraHitEmitter; diff --git a/Aquaria/Continuity.cpp b/Aquaria/Continuity.cpp index 3dcd985..8ad5fde 100644 --- a/Aquaria/Continuity.cpp +++ b/Aquaria/Continuity.cpp @@ -2580,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); @@ -3094,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); + } + } } diff --git a/Aquaria/Web.cpp b/Aquaria/Web.cpp index 1e25a31..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(); 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; From f8ed78d33192db3a5ba5cd1d8fed4b5ba418d65c Mon Sep 17 00:00:00 2001 From: fgenesis Date: Sun, 23 Jun 2013 22:41:35 +0200 Subject: [PATCH 50/50] High framerate problem wasn't fully fixed, let's try this again. Little addition to 7891a2f0113d8. --- Aquaria/Avatar.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Aquaria/Avatar.cpp b/Aquaria/Avatar.cpp index 556b8da..f5c8885 100644 --- a/Aquaria/Avatar.cpp +++ b/Aquaria/Avatar.cpp @@ -6977,7 +6977,11 @@ void Avatar::onUpdate(float dt) { /*collideCheck:*/ - if (!isSwimming() && 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); }