diff --git a/src/cache.h b/src/cache.h index fbdefcc..cd1cd63 100644 --- a/src/cache.h +++ b/src/cache.h @@ -414,20 +414,14 @@ struct WaterCache { for (int x = minX; x < maxX; x++) { TR::Room::Sector &s = r.sectors[x * r.zSectors + z]; - bool hasWater = (s.roomAbove != TR::NO_ROOM && !level->rooms[s.roomAbove].flags.water); - bool hasFlow = false; + bool hasWater = s.roomAbove != TR::NO_ROOM && !level->rooms[s.roomAbove].flags.water; if (hasWater) { - TR::Level::FloorInfo info; - game->getLara()->getFloorInfo(to, vec3(float(x + r.info.x), float(r.info.yBottom), float(z + r.info.z)), info); - if (info.trigCmdCount && info.trigger == TR::Level::Trigger::ACTIVATE) - for (int i = 0; i < info.trigCmdCount; i++) - if (info.trigCmd[i].action == TR::Action::FLOW) { - hasFlow = true; - break; - } + TR::Room &rt = level->rooms[s.roomAbove]; + TR::Room::Sector &st = rt.sectors[x * rt.zSectors + z]; + hasWater = s.ceiling > st.ceiling; } - - m[(x - minX) + w * (z - minZ)] = hasWater ? (hasFlow ? 0xF81F : 0xF800) : 0; + + m[(x - minX) + w * (z - minZ)] = hasWater ? 0xF800 : 0; } size = vec3(float((maxX - minX) * 512), 1.0f, float((maxZ - minZ) * 512)); // half size @@ -785,8 +779,10 @@ struct WaterCache { refract->bind(sDiffuse); reflect->bind(sReflect); + item.mask->bind(sMask); item.data[0]->bind(sNormal); Core::setCulling(cfNone); + Core::setBlending(bmAlpha); #ifdef WATER_USE_GRID vec3 rPosScale[2] = { item.pos, item.size * vec3(1.0f / PLANE_DETAIL, 512.0f, 1.0f / PLANE_DETAIL) }; Core::active.shader->setParam(uPosScale, rPosScale[0], 2); @@ -796,6 +792,7 @@ struct WaterCache { game->getMesh()->renderQuad(); #endif Core::setCulling(cfFront); + Core::setBlending(bmNone); } dropCount = 0; } diff --git a/src/controller.h b/src/controller.h index 241f830..a34a5b1 100644 --- a/src/controller.h +++ b/src/controller.h @@ -58,6 +58,7 @@ struct IGame { virtual void checkTrigger(Controller *controller, bool heavy) {} virtual Controller* addEntity(TR::Entity::Type type, int room, const vec3 &pos, float angle = 0.0f) { return NULL; } + virtual void removeEntity(Controller *controller) {} virtual bool invUse(TR::Entity::Type type) { return false; } virtual void invAdd(TR::Entity::Type type, int count = 1) {} diff --git a/src/format.h b/src/format.h index d70ea6c..76d105e 100644 --- a/src/format.h +++ b/src/format.h @@ -2103,29 +2103,6 @@ namespace TR { return 0; } - int entityAdd(Entity::Type type, int16 room, const vec3 &pos, float rotation, int16 intensity) { - for (int i = entitiesBaseCount; i < entitiesCount; i++) { - Entity &e = entities[i]; - if (!e.controller) { - e.type = type; - e.room = room; - e.x = int(pos.x); - e.y = int(pos.y); - e.z = int(pos.z); - e.rotation = angle(normalizeAngle(rotation)); - e.intensity = intensity; - e.flags.value = 0; - e.modelIndex = getModelIndex(e.type); - return i; - } - } - return -1; - } - - void entityRemove(int entityIndex) { - entities[entityIndex].controller = NULL; - } - int getNextRoom(int floorIndex) const { if (!floorIndex) return NO_ROOM; FloorData *fd = &floors[floorIndex]; diff --git a/src/level.h b/src/level.h index 5025dc5..e401a98 100644 --- a/src/level.h +++ b/src/level.h @@ -319,30 +319,51 @@ struct Level : IGame { } virtual Controller* addEntity(TR::Entity::Type type, int room, const vec3 &pos, float angle) { - int index = level.entityAdd(type, room, pos, angle, -1); - if (index > -1) { + int index; + for (index = level.entitiesBaseCount; index < level.entitiesCount; index++) { TR::Entity &e = level.entities[index]; - if (e.isPickup()) - e.intensity = 4096; - else - if (e.isSprite()) { - if (e.type == TR::Entity::LAVA_PARTICLE || e.type == TR::Entity::FLAME) - e.intensity = 0; // emissive - else - e.intensity = 0x1FFF - level.rooms[room].ambient; - } + if (!e.controller) { + e.type = type; + e.room = room; + e.x = int(pos.x); + e.y = int(pos.y); + e.z = int(pos.z); + e.rotation = TR::angle(normalizeAngle(angle)); + e.intensity = -1; + e.flags.value = 0; + e.modelIndex = level.getModelIndex(e.type); + break; + } + } - Controller *controller = initController(index); - e.controller = controller; + if (index == level.entitiesCount) + return NULL; - if (e.isEnemy() || e.isSprite()) { - controller->flags.active = TR::ACTIVE; - controller->activate(); + TR::Entity &e = level.entities[index]; + if (e.isPickup()) + e.intensity = 4096; + else + if (e.isSprite()) { + if (e.type == TR::Entity::LAVA_PARTICLE || e.type == TR::Entity::FLAME) + e.intensity = 0; // emissive + else + e.intensity = 0x1FFF - level.rooms[room].ambient; } - return controller; + Controller *controller = initController(index); + e.controller = controller; + + if (e.isEnemy() || e.isSprite()) { + controller->flags.active = TR::ACTIVE; + controller->activate(); } - return NULL; + + return controller; + } + + virtual void removeEntity(Controller *controller) { + level.entities[controller->entity].controller = NULL; + delete controller; } virtual bool invUse(TR::Entity::Type type) { @@ -618,9 +639,10 @@ struct Level : IGame { case TR::Entity::RICOCHET : return new Sprite(this, index, true, Sprite::FRAME_RANDOM); case TR::Entity::CENTAUR_STATUE : return new CentaurStatue(this, index); case TR::Entity::CABIN : return new Cabin(this, index); - case TR::Entity::TRAP_FLAME_EMITTER : return new TrapFlameEmitter(this, index); case TR::Entity::LAVA_PARTICLE : return new LavaParticle(this, index); case TR::Entity::TRAP_LAVA_EMITTER : return new TrapLavaEmitter(this, index); + case TR::Entity::FLAME : return new Flame(this, index); + case TR::Entity::TRAP_FLAME_EMITTER : return new TrapFlameEmitter(this, index); case TR::Entity::BOAT : return new Boat(this, index); case TR::Entity::EARTHQUAKE : return new Earthquake(this, index); case TR::Entity::MUTANT_EGG_SMALL : @@ -1359,8 +1381,6 @@ struct Level : IGame { void renderDebug() { if (level.id == TR::TITLE) return; -// Core::mViewInv = camera->mViewInv; -// Core::mView = Core::mViewInv.inverse(); Core::setViewport(0, 0, Core::width, Core::height); camera->setup(true); @@ -1369,39 +1389,6 @@ struct Level : IGame { Input::down[ikF] = false; } - /* - static int snd_index = 0; - if (Input::down[ikG]) { - snd_index = (snd_index + 1) % level.soundsInfoCount; - LOG("play sound: %d\n", snd_index); - lara->playSound(snd_index, lara->pos, 0); - Input::down[ikG] = false; - } - - static int modelIndex = 0; - static bool lastStateK = false; - static int lastEntity = -1; - if (Input::down[ikM]) { - if (!lastStateK) { - lastStateK = true; - modelIndex = (modelIndex + 1) % level.modelsCount; - // modelIndex = (modelIndex + 1) % level.spriteSequencesCount; - LOG("model: %d %d\n", modelIndex, level.spriteSequences[modelIndex].type); - if (lastEntity > -1) { - delete level.entities[lastEntity].controller; - level.entityRemove(lastEntity); - } - vec3 p = lara->pos + lara->getDir() * 256.0f; - lastEntity = level.entityAdd(level.models[modelIndex].type, lara->getRoomIndex(), p.x, p.y - 512, p.z, lara->getEntity().rotation, -1); - level.entities[lastEntity].controller = new Controller(this, lastEntity); - } - } else - lastStateK = false; - - if (lastEntity > -1) - renderEntity(level.entities[lastEntity]); -// renderModel(level.models[modelIndex], level.entities[4]); -*/ Debug::begin(); /* lara->updateEntity(); // TODO clip angle while rotating diff --git a/src/shaders/water.glsl b/src/shaders/water.glsl index 2d57ab2..3ee36a3 100644 --- a/src/shaders/water.glsl +++ b/src/shaders/water.glsl @@ -177,7 +177,7 @@ uniform sampler2D sNormal; vec3 normal = vec3(value.z, -sqrt(1.0 - dot(value.zw, value.zw)), value.w); - vec2 dudv = (uViewProj * vec4(normal.x, 0.0, normal.z, 0.0)).xy; + vec2 dudv = (uViewProj * vec4(normal.x, 0.0, normal.z, 0.0)).xy; vec3 viewVec = normalize(vViewVec); vec3 rv = reflect(-viewVec, normal); @@ -185,7 +185,7 @@ uniform sampler2D sNormal; float spec = pow(max(0.0, dot(rv, lv)), 64.0) * 0.5; - vec2 tc = vProjCoord.xy / vProjCoord.w * 0.5 + 0.5; + vec2 tc = vProjCoord.xy / vProjCoord.w * 0.5 + 0.5; vec4 refrA = texture2D(sDiffuse, uParam.xy * clamp(tc + dudv * uParam.z, 0.0, 0.999) ); vec4 refrB = texture2D(sDiffuse, uParam.xy * tc ); @@ -199,7 +199,7 @@ uniform sampler2D sNormal; float d = abs((vCoord.y - uViewPos.y) / normalize(vViewVec).y); d *= step(0.0, uViewPos.y - vCoord.y); // apply fog only when camera is underwater color.xyz = applyFog(color.xyz, UNDERWATER_COLOR * 0.2, d * WATER_FOG_DIST); - + color.w *= texture2D(sMask, vTexCoord).x; return color; } diff --git a/src/sprite.h b/src/sprite.h index 33b7cd6..f3aa92d 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -50,10 +50,8 @@ struct Sprite : Controller { pos += velocity * (30.0f * Core::deltaTime); - if (remove) { - level->entityRemove(entity); - delete this; - } + if (remove) + game->removeEntity(this); } virtual void render(Frustum *frustum, MeshBuilder *mesh, Shader::Type type, bool caustics) { diff --git a/src/trigger.h b/src/trigger.h index 906d448..ea2d7f4 100644 --- a/src/trigger.h +++ b/src/trigger.h @@ -82,8 +82,7 @@ struct Dart : Controller { getFloorInfo(getRoomIndex(), pos, info); if (pos.y > info.floor || pos.y < info.ceiling || !insideRoom(pos, getRoomIndex())) { game->addEntity(TR::Entity::RICOCHET, getRoomIndex(), pos - dir * 64.0f); // with wall offset - level->entityRemove(entity); - delete this; + game->removeEntity(this); } } }; @@ -120,24 +119,16 @@ struct TrapDartEmitter : Controller { struct Flame : Sprite { static Flame* add(IGame *game, Controller *controller, int jointIndex) { - Flame *flame = NULL; - - TR::Level *level = game->getLevel(); - int roomIndex = controller->getRoomIndex(); - vec3 pos = controller->pos; - - int index = level->entityAdd(TR::Entity::FLAME, roomIndex, pos, 0, 0); - if (index > -1) { - flame = new Flame(game, index, jointIndex); - level->entities[index].controller = flame; - } + Flame *flame = (Flame*)game->addEntity(TR::Entity::FLAME, controller->getRoomIndex(), controller->pos); + if (flame) + flame->jointIndex = jointIndex; return flame; } int jointIndex; float sleep; - Flame(IGame *game, int entity, int jointIndex) : Sprite(game, entity, false, Sprite::FRAME_ANIMATED), jointIndex(jointIndex), sleep(0.0f) { + Flame(IGame *game, int entity) : Sprite(game, entity, false, Sprite::FRAME_ANIMATED), jointIndex(0), sleep(0.0f) { time = randf() * 3.0f; activate(); } @@ -150,8 +141,7 @@ struct Flame : Sprite { if (jointIndex > -1) { if (lara->stand == Character::STAND_UNDERWATER) { - level->entityRemove(entity); - delete this; + game->removeEntity(this); return; } @@ -185,10 +175,9 @@ struct TrapFlameEmitter : Controller { void virtual update() { if (!isActive()) { if (flame) { - level->entityRemove(flame->entity); - delete flame; - flame = NULL; Sound::stop(TR::SND_FLAME); + game->removeEntity(flame); + flame = NULL; } return; } @@ -231,8 +220,7 @@ struct LavaParticle : Sprite { if (hit || pos.y > info.floor || pos.y < info.ceiling) { if (hit || ++bounces > 4) { - level->entityRemove(entity); - delete this; + game->removeEntity(this); return; } intensity = max(0.0f, 1.0f - bounces * 0.25f); @@ -379,13 +367,15 @@ struct Block : Controller { // check for trapdoor int px = int(p.x) / 1024; int pz = int(p.z) / 1024; - for (int i = 0; i < info.trigCmdCount; i++) + for (int i = 0; i < info.trigCmdCount; i++) { if (info.trigCmd[i].action == TR::Action::ACTIVATE) { TR::Entity &e = level->entities[info.trigCmd[i].args]; vec3 objPos = ((Controller*)e.controller)->pos; if ((e.type == TR::Entity::TRAP_DOOR_1 || e.type == TR::Entity::TRAP_DOOR_2) && px == int(objPos.x) / 1024 && pz == int(objPos.z) / 1024) return false; - } + } else if (info.trigCmd[i].action == TR::Action::CAMERA_SWITCH) + i++; // skip camera switch delay info + } // check Laras destination position if (!push) { @@ -895,11 +885,8 @@ struct ThorHammer : Controller { Controller *block; ThorHammer(IGame *game, int entity) : Controller(game, entity) { - int index = level->entityAdd(TR::Entity::HAMMER_BLOCK, getRoomIndex(), pos, angle.y, -1); - if (index > -1) { - block = new Controller(game, index); - level->entities[index].controller = block; - } + block = game->addEntity(TR::Entity::HAMMER_BLOCK, getRoomIndex(), pos, angle.y); + ASSERT(block); flags.collision = block->flags.collision = false; }