summary refs log tree commit diff stats
path: root/data/maps/the_entry/rooms/Shop Entrance.txtpb
blob: db9ea2f7adfff5fa46d29f0637d14ede32ec7d8c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
name: "Shop Entrance"
display_name: "Starting Room"
panels {
  name: "TURN"
  path: "Panels/Entry/l_opener_2"
  clue: "turn"
  answer: "turned"
  symbols: "sparkles"
}
ports {
  name: "SHOP"
  path: "Components/Warps/worldport13"
  orientation: "east"
}
#n227'>227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
#include "character_system.h"
#include "consts.h"
#include "mixer.h"
#include "sprite.h"
#include "game.h"
#include "transform_system.h"
#include "animation_system.h"
#include "script_system.h"

void CharacterSystem::initSprite(int spriteId) {
  Sprite& sprite = game_.getSprite(spriteId);
  sprite.orientable = true;
}

void CharacterSystem::addSpriteToParty(int leaderId, int followerId) {
  Sprite& leader = game_.getSprite(leaderId);
  Sprite& follower = game_.getSprite(followerId);

  vec2i targetPos = leader.loc;

  if (!leader.followers.empty()) {
    Sprite& backFollower = game_.getSprite(leader.followers.back());
    follower.trail = backFollower.trail;
    targetPos = backFollower.loc;
  }

  Direction toFace = leader.dir;
  if (targetPos != follower.loc) {
    toFace = directionFacingPoint(targetPos - follower.loc);
  }

  for (int i=0; i<PARTY_FRAME_DELAY; i++) {
    vec2i tween = ((follower.loc - targetPos) * i) / static_cast<double>(PARTY_FRAME_DELAY) + targetPos;
    follower.trail.push_front({.pos = tween, .dir = toFace});
  }

  leader.followers.push_back(followerId);

  game_.getSystem<AnimationSystem>().setSpriteAnimation(followerId, "still");
}

void CharacterSystem::moveInDirection(int spriteId, Direction dir) {
  Sprite& sprite = game_.getSprite(spriteId);

  game_.getSystem<AnimationSystem>().setSpriteDirection(spriteId, dir);

  if (sprite.characterState == CharacterState::Still) {
    setPartyState(spriteId, CharacterState::Walking);
  } else if (sprite.characterState == CharacterState::Crouching) {
    for (int followerId : sprite.followers) {
      game_.getSystem<AnimationSystem>().setSpriteDirection(followerId, dir);
    }
  }
}

void CharacterSystem::stopDirecting(int spriteId) {
  Sprite& sprite = game_.getSprite(spriteId);

  if (sprite.characterState == CharacterState::Walking) {
    setPartyState(spriteId, CharacterState::Still);
  }
}

void CharacterSystem::tick(double dt) {
  inputTimer_.accumulate(dt);
  while (inputTimer_.step()) {
    for (int spriteId : game_.getSprites()) {
      Sprite& sprite = game_.getSprite(spriteId);

      if (sprite.orientable) {
        vec2i pLoc = sprite.loc;

        if (sprite.characterState == CharacterState::Still ||
            sprite.characterState == CharacterState::Crouching) {
          continue;
        }

        int speed = MOVEMENT_SPEED;
        if (sprite.characterState == CharacterState::Running) {
          speed *= 2;
        }

        pLoc += (unitVecInDirection(sprite.dir) * speed);

        // Check collision.
        CollisionResult collision = game_.getSystem<TransformSystem>().checkCollision(spriteId, pLoc, sprite.dir);
        bool blocked = collision.horiz.blocked || collision.vert.blocked;

        if (collision.horiz.blocked) {
          pLoc.x() = sprite.loc.x();//(newColPosDR * map.getTileSize() - (collisionBox / 2)).x() - 1;
        } else if (collision.horiz.colliderSprite != -1) {
          Sprite& collider = game_.getSprite(collision.horiz.colliderSprite);

          if (collider.walkthroughScript != "") {
            game_.getSystem<ScriptSystem>().runScript(collider.walkthroughScript);
          }
        }

        if (collision.vert.blocked) {
          pLoc.y() = sprite.loc.y();//(newColPosDR * map.getTileSize() - (collisionBox / 2)).x() - 1;
        } else if (collision.vert.colliderSprite != -1) {
          Sprite& collider = game_.getSprite(collision.vert.colliderSprite);

          if (collider.walkthroughScript != "") {
            game_.getSystem<ScriptSystem>().runScript(collider.walkthroughScript);
          }
        }

        if (blocked && sprite.characterState == CharacterState::Running) {
          stopRunning(spriteId);
          game_.getMixer().playSound("../res/sfx/bump.wav");
        }

        // Move everything
        if (pLoc != sprite.loc) {
          game_.getSystem<TransformSystem>().moveSprite(spriteId, pLoc);

          if (sprite.characterState == CharacterState::Running) {
            const Map& map = game_.getMap();

            vec2i newMapTileLoc = pLoc / map.getTileSize();
            StepType newTileStep = map.getStepType(newMapTileLoc.x(), newMapTileLoc.y());
            if (sprite.stepType != newTileStep) {
              stopRunningSound(sprite);

              sprite.stepType = newTileStep;

              if (newTileStep != StepType::none) {
                sprite.runningSfxChannel = game_.getMixer().loopSound(runningSfxForStepType(newTileStep));
              }
            }
          }

          for (int followerId : sprite.followers) {
            Sprite& pNext = game_.getSprite(followerId);
            const Movement& posdir = pNext.trail.front();
            game_.getSystem<TransformSystem>().moveSprite(followerId, posdir.pos);
            game_.getSystem<AnimationSystem>().setSpriteDirection(followerId, posdir.dir);

            pNext.trail.pop_front();
            pNext.trail.push_back({.pos = pLoc, .dir = sprite.dir});
          }
        }
      }
    }
  }
}

void CharacterSystem::beginCrouch(int spriteId) {
  Sprite& sprite = game_.getSprite(spriteId);

  if (sprite.characterState == CharacterState::Running) {
    stopRunning(spriteId);
  } else {
    setPartyState(spriteId, CharacterState::Crouching);
  }
}

void CharacterSystem::endCrouch(int spriteId) {
  Sprite& sprite = game_.getSprite(spriteId);

  if (sprite.characterState == CharacterState::Crouching) {
    startRunning(spriteId);
  }
}

void CharacterSystem::startRunning(int spriteId) {
  Sprite& sprite = game_.getSprite(spriteId);
  setPartyState(spriteId, CharacterState::Running);

  for (int followerId : sprite.followers) {
    // Halve the movement buffer for the followers.
    Sprite& follower = game_.getSprite(followerId);
    std::deque<Movement> newMove;

    while (!follower.trail.empty()) {
      newMove.push_back(follower.trail.front());
      follower.trail.pop_front();
      follower.trail.pop_front();
    }

    follower.trail = std::move(newMove);
  }
}

void CharacterSystem::stopRunning(int spriteId) {
  Sprite& sprite = game_.getSprite(spriteId);
  setPartyState(spriteId, CharacterState::Still);
  stopRunningSound(sprite);

  // Double the movement buffer for the followers.
  for (int followerId : sprite.followers) {
    Sprite& follower = game_.getSprite(followerId);

    std::deque<Movement> newMove;
    vec2i lastPos = follower.loc;

    while (!follower.trail.empty()) {
      Movement m1 = follower.trail.front();
      Movement m2 = m1;
      m1.pos = (m1.pos + lastPos) / 2;
      lastPos = m2.pos;

      newMove.push_back(m1);
      newMove.push_back(m2);
      follower.trail.pop_front();
    }

    follower.trail = std::move(newMove);
  }
}

void CharacterSystem::setPartyState(int spriteId, CharacterState state) {
  std::string animName;
  switch (state) {
    case CharacterState::Still: {
      animName = "still";
      break;
    }
    case CharacterState::Walking: {
      animName = "walk";
      break;
    }
    case CharacterState::Crouching: {
      animName = "crouch";
      break;
    }
    case CharacterState::Running: {
      animName = "run";
      break;
    }
  }

  Sprite& sprite = game_.getSprite(spriteId);
  sprite.characterState = state;

  game_.getSystem<AnimationSystem>().setSpriteAnimation(spriteId, animName);
  for (int followerId : sprite.followers) {
    game_.getSystem<AnimationSystem>().setSpriteAnimation(followerId, animName);
  }
}

void CharacterSystem::stopRunningSound(Sprite& sprite) {
  sprite.stepType = StepType::none;
  if (sprite.runningSfxChannel != -1) {
    game_.getMixer().stopChannel(sprite.runningSfxChannel);
    sprite.runningSfxChannel = -1;
  }
}

void CharacterSystem::halt(int spriteId) {
  // Because special stuff happens when we stop running, we have to handle the
  // running case here.
  Sprite& sprite = game_.getSprite(spriteId);
  if (sprite.characterState == CharacterState::Running) {
    stopRunning(spriteId);
  } else {
    // Other than that, it is simple to go to Still from Walking or Crouching.
    setPartyState(spriteId, CharacterState::Still);
  }
}

void CharacterSystem::clearSpriteCache() {
  for (Sprite& sprite : game_.getSprites() | game_.spriteView()) {
    if (sprite.runningSfxChannel != -1) {
      stopRunningSound(sprite);
    }
  }
}