示例#1
0
int CharacterInfo::update_character_animating(int &aa, int &doing_nothing)
{
	// not moving, but animating
    // idleleft is <0 while idle view is playing (.animating is 0)
    if (((animating != 0) || (idleleft < 0)) &&
        ((walking == 0) || ((flags & CHF_MOVENOTWALK) != 0)) &&
        (room == displayed_room)) 
    {
      const bool is_voice = channels[SCHAN_SPEECH] != NULL;

      doing_nothing = 0;
      // idle anim doesn't count as doing something
      if (idleleft < 0)
        doing_nothing = 1;

      if (wait>0) wait--;
      else if ((char_speaking == aa) && (game.options[OPT_LIPSYNCTEXT] != 0)) {
        // currently talking with lip-sync speech
        int fraa = frame;
        wait = update_lip_sync (view, loop, &fraa) - 1;
        // closed mouth at end of sentence
        // NOTE: standard lip-sync is synchronized with text timer, not voice file
        if (play.speech_in_post_state ||
            (play.messagetime >= 0) && (play.messagetime < play.close_mouth_speech_time))
          frame = 0;

        if (frame != fraa) {
          frame = fraa;
          CheckViewFrameForCharacter(this);
        }
        
        //continue;
		return RETURN_CONTINUE;
      }
      else {
        int oldframe = frame;
        if (animating & CHANIM_BACKWARDS) {
          frame--;
          if (frame < 0) {
            // if the previous loop is a Run Next Loop one, go back to it
            if ((loop > 0) && 
              (views[view].loops[loop - 1].RunNextLoop())) {

              loop --;
              frame = views[view].loops[loop].numFrames - 1;
            }
            else if (animating & CHANIM_REPEAT) {

              frame = views[view].loops[loop].numFrames - 1;

              while (views[view].loops[loop].RunNextLoop()) {
                loop++;
                frame = views[view].loops[loop].numFrames - 1;
              }
            }
            else {
              frame++;
              animating = 0;
            }
          }
        }
        else
          frame++;

        if ((aa == char_speaking) &&
             (play.speech_in_post_state ||
             (!is_voice) &&
             (play.close_mouth_speech_time > 0) &&
             (play.messagetime < play.close_mouth_speech_time))) {
          // finished talking - stop animation
          animating = 0;
          frame = 0;
        }

        if (frame >= views[view].loops[loop].numFrames) {
          
          if (views[view].loops[loop].RunNextLoop()) 
          {
            if (loop+1 >= views[view].numLoops)
              quit("!Animating character tried to overrun last loop in view");
            loop++;
            frame=0;
          }
          else if ((animating & CHANIM_REPEAT)==0) {
            animating=0;
            frame--;
            // end of idle anim
            if (idleleft < 0) {
              // constant anim, reset (need this cos animating==0)
              if (idletime == 0)
                frame = 0;
              // one-off anim, stop
              else {
                ReleaseCharacterView(aa);
                idleleft=idletime;
              }
            }
          }
          else {
            frame=0;
            // if it's a multi-loop animation, go back to start
            if (play.no_multiloop_repeat == 0) {
              while ((loop > 0) && 
                  (views[view].loops[loop - 1].RunNextLoop()))
                loop--;
            }
          }
        }
        wait = views[view].loops[loop].frames[frame].speed;
        // idle anim doesn't have speed stored cos animating==0
        if (idleleft < 0)
          wait += animspeed+5;
        else 
          wait += (animating >> 8) & 0x00ff;

        if (frame != oldframe)
          CheckViewFrameForCharacter(this);
      }
    }

	return 0;
}
示例#2
0
// the 'cmdsrun' parameter counts how many commands are run.
// if a 'Inv Item Was Used' check does not pass, it doesn't count
// so cmdsrun remains 0 if no inventory items matched
int run_interaction_commandlist (InteractionCommandList *nicl, int *timesrun, int*cmdsrun) {
    size_t i;

    if (nicl == NULL)
        return -1;

    for (i = 0; i < nicl->Cmds.size(); i++) {
        cmdsrun[0] ++;
        int room_was = play.room_changes;

        switch (nicl->Cmds[i].Type) {
      case 0:  // Do nothing
          break;
      case 1:  // Run script
          { 
              TempEip tempip(4001);
              RuntimeScriptValue rval_null;
              update_mp3();
                  if ((strstr(evblockbasename,"character")!=0) || (strstr(evblockbasename,"inventory")!=0)) {
                      // Character or Inventory (global script)
                      const char *torun = make_ts_func_name(evblockbasename,evblocknum,nicl->Cmds[i].Data[0].Value);
                      // we are already inside the mouseclick event of the script, can't nest calls
                      QueueScriptFunction(kScInstGame, torun);
                  }
                  else {
                      // Other (room script)
                      const char *torun = make_ts_func_name(evblockbasename,evblocknum,nicl->Cmds[i].Data[0].Value);
                      QueueScriptFunction(kScInstRoom, torun);
                  }
                  update_mp3();
                      break;
          }
      case 2:  // Add score (first time)
          if (timesrun[0] > 0)
              break;
          timesrun[0] ++;
      case 3:  // Add score
          GiveScore (IPARAM1);
          break;
      case 4:  // Display Message
          /*        if (comprdata<0)
          display_message_aschar=evb->data[ss];*/
          DisplayMessage(IPARAM1);
          break;
      case 5:  // Play Music
          PlayMusicResetQueue(IPARAM1);
          break;
      case 6:  // Stop Music
          stopmusic ();
          break;
      case 7:  // Play Sound
          play_sound (IPARAM1);
          break;
      case 8:  // Play Flic
          play_flc_file(IPARAM1, IPARAM2);
          break;
      case 9:  // Run Dialog
          { int room_was = play.room_changes;
          RunDialog(IPARAM1);
          // if they changed room within the dialog script,
          // the interaction command list is no longer valid
          if (room_was != play.room_changes)
              return -1;
          }
          break;
      case 10: // Enable Dialog Option
          SetDialogOption (IPARAM1, IPARAM2, 1);
          break;
      case 11: // Disable Dialog Option
          SetDialogOption (IPARAM1, IPARAM2, 0);
          break;
      case 12: // Go To Screen
          Character_ChangeRoomAutoPosition(playerchar, IPARAM1, IPARAM2);
          return -1;
      case 13: // Add Inventory
          add_inventory (IPARAM1);
          break;
      case 14: // Move Object
          MoveObject (IPARAM1, IPARAM2, IPARAM3, IPARAM4);
          // if they want to wait until finished, do so
          if (IPARAM5)
              GameLoopUntilEvent(UNTIL_MOVEEND,(long)&objs[IPARAM1].moving);
          break;
      case 15: // Object Off
          ObjectOff (IPARAM1);
          break;
      case 16: // Object On
          ObjectOn (IPARAM1);
          break;
      case 17: // Set Object View
          SetObjectView (IPARAM1, IPARAM2);
          break;
      case 18: // Animate Object
          AnimateObject (IPARAM1, IPARAM2, IPARAM3, IPARAM4);
          break;
      case 19: // Move Character
          if (IPARAM4)
              MoveCharacterBlocking (IPARAM1, IPARAM2, IPARAM3, 0);
          else
              MoveCharacter (IPARAM1, IPARAM2, IPARAM3);
          break;
      case 20: // If Inventory Item was used
          if (play.usedinv == IPARAM1) {
              if (game.options[OPT_NOLOSEINV] == 0)
                  lose_inventory (play.usedinv);
              if (run_interaction_commandlist (nicl->Cmds[i].Children.get(), timesrun, cmdsrun))
                  return -1;
          }
          else
              cmdsrun[0] --;
          break;
      case 21: // if player has inventory item
          if (playerchar->inv[IPARAM1] > 0)
              if (run_interaction_commandlist (nicl->Cmds[i].Children.get(), timesrun, cmdsrun))
                  return -1;
          break;
      case 22: // if a character is moving
          if (game.chars[IPARAM1].walking)
              if (run_interaction_commandlist (nicl->Cmds[i].Children.get(), timesrun, cmdsrun))
                  return -1;
          break;
      case 23: // if two variables are equal
          if (IPARAM1 == IPARAM2)
              if (run_interaction_commandlist (nicl->Cmds[i].Children.get(), timesrun, cmdsrun))
                  return -1;
          break;
      case 24: // Stop character walking
          StopMoving (IPARAM1);
          break;
      case 25: // Go to screen at specific co-ordinates
          NewRoomEx (IPARAM1, IPARAM2, IPARAM3);
          return -1;
      case 26: // Move NPC to different room
          if (!is_valid_character(IPARAM1))
              quit("!Move NPC to different room: invalid character specified");
          game.chars[IPARAM1].room = IPARAM2;
          break;
      case 27: // Set character view
          SetCharacterView (IPARAM1, IPARAM2);
          break;
      case 28: // Release character view
          ReleaseCharacterView (IPARAM1);
          break;
      case 29: // Follow character
          FollowCharacter (IPARAM1, IPARAM2);
          break;
      case 30: // Stop following
          FollowCharacter (IPARAM1, -1);
          break;
      case 31: // Disable hotspot
          DisableHotspot (IPARAM1);
          break;
      case 32: // Enable hotspot
          EnableHotspot (IPARAM1);
          break;
      case 33: // Set variable value
          get_interaction_variable(nicl->Cmds[i].Data[0].Value)->Value = IPARAM2;
          break;
      case 34: // Run animation
          scAnimateCharacter(IPARAM1, IPARAM2, IPARAM3, 0);
          GameLoopUntilEvent(UNTIL_SHORTIS0,(long)&game.chars[IPARAM1].animating);
          break;
      case 35: // Quick animation
          SetCharacterView (IPARAM1, IPARAM2);
          scAnimateCharacter(IPARAM1, IPARAM3, IPARAM4, 0);
          GameLoopUntilEvent(UNTIL_SHORTIS0,(long)&game.chars[IPARAM1].animating);
          ReleaseCharacterView (IPARAM1);
          break;
      case 36: // Set idle animation
          SetCharacterIdle (IPARAM1, IPARAM2, IPARAM3);
          break;
      case 37: // Disable idle animation
          SetCharacterIdle (IPARAM1, -1, -1);
          break;
      case 38: // Lose inventory item
          lose_inventory (IPARAM1);
          break;
      case 39: // Show GUI
          InterfaceOn (IPARAM1);
          break;
      case 40: // Hide GUI
          InterfaceOff (IPARAM1);
          break;
      case 41: // Stop running more commands
          return -1;
      case 42: // Face location
          FaceLocation (IPARAM1, IPARAM2, IPARAM3);
          break;
      case 43: // Pause command processor
          scrWait (IPARAM1);
          break;
      case 44: // Change character view
          ChangeCharacterView (IPARAM1, IPARAM2);
          break;
      case 45: // If player character is
          if (GetPlayerCharacter() == IPARAM1)
              if (run_interaction_commandlist (nicl->Cmds[i].Children.get(), timesrun, cmdsrun))
                  return -1;
          break;
      case 46: // if cursor mode is
          if (GetCursorMode() == IPARAM1)
              if (run_interaction_commandlist (nicl->Cmds[i].Children.get(), timesrun, cmdsrun))
                  return -1;
          break;
      case 47: // if player has been to room
          if (HasBeenToRoom(IPARAM1))
              if (run_interaction_commandlist (nicl->Cmds[i].Children.get(), timesrun, cmdsrun))
                  return -1;
          break;
      default:
          quit("unknown new interaction command");
          break;
        }

        // if the room changed within the action, nicl is no longer valid
        if (room_was != play.room_changes)
            return -1;
    }
    return 0;

}
void walk_character(int chac,int tox,int toy,int ignwal, bool autoWalkAnims) {
  CharacterInfo*chin=&game.chars[chac];
  if (chin->room!=displayed_room)
    quit("!MoveCharacter: character not in current room");

  chin->flags &= ~CHF_MOVENOTWALK;

  int toxPassedIn = tox, toyPassedIn = toy;
  int charX = convert_to_low_res(chin->x);
  int charY = convert_to_low_res(chin->y);
  tox = convert_to_low_res(tox);
  toy = convert_to_low_res(toy);

  if ((tox == charX) && (toy == charY)) {
    StopMoving(chac);
    DEBUG_CONSOLE("%s already at destination, not moving", chin->scrname);
    return;
  }

  if ((chin->animating) && (autoWalkAnims))
    chin->animating = 0;

  if (chin->idleleft < 0) {
    ReleaseCharacterView(chac);
    chin->idleleft=chin->idletime;
  }
  // stop them to make sure they're on a walkable area
  // but save their frame first so that if they're already
  // moving it looks smoother
  int oldframe = chin->frame;
  int waitWas = 0, animWaitWas = 0;
  // if they are currently walking, save the current Wait
  if (chin->walking)
  {
    waitWas = chin->walkwait;
    animWaitWas = charextra[chac].animwait;
  }

  StopMoving (chac);
  chin->frame = oldframe;
  // use toxPassedIn cached variable so the hi-res co-ordinates
  // are still displayed as such
  DEBUG_CONSOLE("%s: Start move to %d,%d", chin->scrname, toxPassedIn, toyPassedIn);

  int move_speed_x = chin->walkspeed;
  int move_speed_y = chin->walkspeed;

  if (chin->walkspeed_y != UNIFORM_WALK_SPEED)
    move_speed_y = chin->walkspeed_y;

  if ((move_speed_x == 0) && (move_speed_y == 0)) {
    debug_log("Warning: MoveCharacter called for '%s' with walk speed 0", chin->name);
  }

  set_route_move_speed(move_speed_x, move_speed_y);
  set_color_depth(8);
  int mslot=find_route(charX, charY, tox, toy, prepare_walkable_areas(chac), chac+CHMLSOFFS, 1, ignwal);
  set_color_depth(final_col_dep);
  if (mslot>0) {
    chin->walking = mslot;
    mls[mslot].direct = ignwal;

    if ((game.options[OPT_NATIVECOORDINATES] != 0) &&
        (game.default_resolution > 2))
    {
      convert_move_path_to_high_res(&mls[mslot]);
    }
    // cancel any pending waits on current animations
    // or if they were already moving, keep the current wait - 
    // this prevents a glitch if MoveCharacter is called when they
    // are already moving
    if (autoWalkAnims)
    {
      chin->walkwait = waitWas;
      charextra[chac].animwait = animWaitWas;

      if (mls[mslot].pos[0] != mls[mslot].pos[1]) {
        fix_player_sprite(&mls[mslot],chin);
      }
    }
    else
      chin->flags |= CHF_MOVENOTWALK;
  }
  else if (autoWalkAnims) // pathfinder couldn't get a route, stand them still
    chin->frame = 0;
}