2018-12-30 18:00:05 +08:00
using System ;
using CustomNPCFramework.Framework.Enums ;
using CustomNPCFramework.Framework.ModularNpcs ;
using CustomNPCFramework.Framework.ModularNpcs.ModularRenderers ;
2018-02-24 15:16:10 +08:00
using Microsoft.Xna.Framework ;
2018-02-24 11:10:56 +08:00
using Microsoft.Xna.Framework.Graphics ;
using StardewValley ;
namespace CustomNPCFramework.Framework.NPCS
{
2018-12-30 18:00:05 +08:00
// TODO:
// - Add in an resource loader for all of the character graphics and use it to populate some character graphics.
// - Make .json way to load in assets to the mod.
// - Organize it all.
// - Profit???
public class ExtendedNpc : NPC
2018-02-24 11:10:56 +08:00
{
2018-12-30 18:00:05 +08:00
/// <summary>The custom character renderer for this npc.</summary>
2018-02-24 15:16:10 +08:00
public BasicRenderer characterRenderer ;
2018-02-24 17:04:35 +08:00
public bool hasBeenKissedToday ;
public Point previousEndPoint ;
public bool returningToEndPoint ;
public bool hasSaidAfternoonDialogue ;
public int timeAfterSquare ;
2018-02-24 15:40:34 +08:00
2018-12-30 18:00:05 +08:00
/// <summary>Used to hold sprite information to be used in the case the npc renderer is null.</summary>
2018-02-24 17:04:35 +08:00
public Sprite spriteInformation ;
2018-12-30 18:00:05 +08:00
/// <summary>Used to hold the portrait information for the npc and display it.</summary>
2018-02-24 17:04:35 +08:00
public Portrait portraitInformation ;
2018-03-04 19:36:19 +08:00
2018-12-30 18:00:05 +08:00
/// <summary>The default location for this npc to reside in.</summary>
2018-03-04 19:36:19 +08:00
public GameLocation defaultLocation ;
2018-12-30 18:00:05 +08:00
/// <summary>Construct an instance.</summary>
public ExtendedNpc ( ) { }
2018-03-05 07:21:39 +08:00
2018-12-30 18:00:05 +08:00
/// <summary>Construct an instance.</summary>
2018-03-20 14:01:43 +08:00
/// <param name="sprite">The sprite for the character.</param>
/// <param name="position">The position of the npc on the map.</param>
/// <param name="facingDirection">The direction of the npc</param>
/// <param name="name">The name of the npc.</param>
2018-12-30 18:00:05 +08:00
public ExtendedNpc ( Sprite sprite , Vector2 position , int facingDirection , string name )
: base ( sprite . sprite , position , facingDirection , name )
2018-03-05 07:21:39 +08:00
{
this . characterRenderer = null ;
2018-12-30 18:00:05 +08:00
this . Portrait = null ;
2018-03-05 07:21:39 +08:00
this . portraitInformation = null ;
this . spriteInformation = sprite ;
2018-12-30 18:00:05 +08:00
this . spriteInformation ? . setCharacterSpriteFromThis ( this ) ;
2018-05-01 09:21:31 +08:00
this . swimming . Value = false ;
2018-03-05 07:21:39 +08:00
}
2018-12-30 18:00:05 +08:00
/// <summary>Construct an instance.</summary>
2018-03-20 14:01:43 +08:00
/// <param name="sprite">The sprite for the character.</param>
/// <param name="portrait">The portrait texture for this npc.</param>
/// <param name="position">The position of the npc on the map.</param>
/// <param name="facingDirection">The direction of the npc</param>
/// <param name="name">The name of the npc.</param>
2018-12-30 18:00:05 +08:00
public ExtendedNpc ( Sprite sprite , Portrait portrait , Vector2 position , int facingDirection , string name )
: base ( sprite . sprite , position , facingDirection , name )
2018-03-05 07:21:39 +08:00
{
this . characterRenderer = null ;
this . portraitInformation = portrait ;
2018-12-30 18:00:05 +08:00
this . portraitInformation ? . setCharacterPortraitFromThis ( this ) ;
2018-03-05 07:21:39 +08:00
this . spriteInformation = sprite ;
this . spriteInformation . setCharacterSpriteFromThis ( this ) ;
2018-05-01 09:21:31 +08:00
this . swimming . Value = false ;
2018-03-05 07:21:39 +08:00
}
2018-12-30 18:00:05 +08:00
/// <summary>Construct an instance.</summary>
2018-03-20 14:01:43 +08:00
/// <param name="sprite">The sprite for the character to use incase the renderer is null.</param>
/// <param name="renderer">The custom npc render. Used to draw the npcfrom a collection of assets.</param>
/// <param name="position">The position of the npc on the map.</param>
/// <param name="facingDirection">The direction of the npc</param>
/// <param name="name">The name of the npc.</param>
2018-12-30 18:00:05 +08:00
public ExtendedNpc ( Sprite sprite , BasicRenderer renderer , Vector2 position , int facingDirection , string name )
: base ( sprite . sprite , position , facingDirection , name )
2018-02-24 11:10:56 +08:00
{
2018-02-24 15:40:34 +08:00
this . characterRenderer = renderer ;
2018-12-30 18:00:05 +08:00
this . Portrait = null ;
2018-02-24 17:04:35 +08:00
this . portraitInformation = null ;
this . spriteInformation = sprite ;
2018-12-30 18:00:05 +08:00
this . spriteInformation ? . setCharacterSpriteFromThis ( this ) ;
2018-05-01 09:21:31 +08:00
this . swimming . Value = false ;
2018-02-24 11:10:56 +08:00
}
2018-12-30 18:00:05 +08:00
/// <summary>Construct an instance.</summary>
2018-03-20 14:01:43 +08:00
/// <param name="sprite">The sprite for the npc to use incase the renderer is null.</param>
/// <param name="renderer">The custom npc renderer used to draw the npc from the collection of textures.</param>
/// <param name="portrait">The portrait texture for the npc.</param>
/// <param name="position">The positon for the npc to be.</param>
/// <param name="facingDirection">The direction for the npc to face.</param>
/// <param name="name">The name for the npc.</param>
2018-12-30 18:00:05 +08:00
public ExtendedNpc ( Sprite sprite , BasicRenderer renderer , Portrait portrait , Vector2 position , int facingDirection , string name )
: base ( sprite . sprite , position , facingDirection , name )
2018-02-24 15:40:34 +08:00
{
this . characterRenderer = renderer ;
2018-02-24 17:04:35 +08:00
this . portraitInformation = portrait ;
2018-12-30 18:00:05 +08:00
this . portraitInformation ? . setCharacterPortraitFromThis ( this ) ;
2018-02-24 17:05:58 +08:00
this . spriteInformation = sprite ;
2018-12-30 18:00:05 +08:00
this . spriteInformation ? . setCharacterSpriteFromThis ( this ) ;
2018-05-01 09:21:31 +08:00
this . swimming . Value = false ;
2018-02-24 15:40:34 +08:00
}
2018-02-24 11:10:56 +08:00
2018-12-30 18:00:05 +08:00
/// <summary>Used to reload the sprite for the npc.</summary>
2018-05-01 09:21:31 +08:00
public void reloadSprite ( )
2018-02-24 11:10:56 +08:00
{
2018-02-24 17:04:35 +08:00
if ( this . characterRenderer = = null )
2018-02-24 11:10:56 +08:00
{
2018-02-24 17:04:35 +08:00
this . spriteInformation . reload ( ) ;
try
{
this . portraitInformation . reload ( ) ;
}
2018-12-30 18:00:05 +08:00
catch
2018-02-24 17:04:35 +08:00
{
2018-12-30 18:00:05 +08:00
this . Portrait = null ;
2018-02-24 17:04:35 +08:00
}
2018-02-24 15:40:34 +08:00
}
else
{
2018-02-24 17:04:35 +08:00
this . characterRenderer . reloadSprites ( ) ;
try
{
this . portraitInformation . reload ( ) ;
}
2018-12-30 18:00:05 +08:00
catch
2018-02-24 17:04:35 +08:00
{
2018-12-30 18:00:05 +08:00
this . Portrait = null ;
2018-02-24 17:04:35 +08:00
}
2018-02-24 15:40:34 +08:00
}
2018-12-30 18:00:05 +08:00
if ( ! Game1 . newDay & & Game1 . gameMode ! = 6 )
2018-02-24 15:40:34 +08:00
return ;
this . faceDirection ( this . DefaultFacingDirection ) ;
this . scheduleTimeToTry = 9999999 ;
2018-02-24 17:04:35 +08:00
this . previousEndPoint = new Point ( ( int ) this . DefaultPosition . X / Game1 . tileSize , ( int ) this . DefaultPosition . Y / Game1 . tileSize ) ;
2018-02-24 15:40:34 +08:00
this . Schedule = this . getSchedule ( Game1 . dayOfMonth ) ;
this . faceDirection ( this . defaultFacingDirection ) ;
2018-05-01 09:21:31 +08:00
this . Sprite . standAndFaceDirection ( this . defaultFacingDirection ) ;
2018-12-30 18:00:05 +08:00
2018-02-24 15:40:34 +08:00
if ( this . isMarried ( ) )
2018-06-09 02:40:23 +08:00
this . marriageDuties ( ) ;
2018-02-24 15:40:34 +08:00
try
2018-02-24 11:10:56 +08:00
{
2018-05-01 09:21:31 +08:00
this . displayName = this . Name ;
2018-02-24 15:40:34 +08:00
}
2018-12-30 18:00:05 +08:00
catch { }
2018-02-24 15:40:34 +08:00
}
2018-12-30 18:00:05 +08:00
/// <summary>Functionality used when interacting with the npc.</summary>
public override bool checkAction ( Farmer who , GameLocation l )
2018-02-24 15:40:34 +08:00
{
2018-03-04 20:36:46 +08:00
base . checkAction ( who , l ) ;
2018-02-24 15:40:34 +08:00
return false ;
2018-02-24 11:10:56 +08:00
}
2018-12-30 18:00:05 +08:00
/// <summary>Used to move the npc. Different code is used depending if the character renderer is null or not.</summary>
2018-02-24 15:40:34 +08:00
public override void MovePosition ( GameTime time , xTile . Dimensions . Rectangle viewport , GameLocation currentLocation )
{
2018-03-19 07:06:49 +08:00
if ( this . characterRenderer ! = null )
2018-12-30 18:00:05 +08:00
this . ModularMovement ( time , viewport , currentLocation ) ;
2018-03-19 07:06:49 +08:00
else
2018-12-30 18:00:05 +08:00
this . NonModularMovement ( time , viewport , currentLocation ) ;
2018-03-19 07:06:49 +08:00
}
2018-12-30 18:00:05 +08:00
/// <summary>Set's the npc to move a certain direction and then executes the movement.</summary>
/// <param name="moveDirection">The direction to move the npc.</param>
2018-03-19 07:06:49 +08:00
/// <param name="Move">Set's the npc's sprite to halt if Move=false. Else set it to true.</param>
2018-12-30 18:00:05 +08:00
public virtual void SetMovingAndMove ( GameTime time , xTile . Dimensions . Rectangle viewport , GameLocation currentLocation , Direction moveDirection , bool Move = true )
2018-03-19 07:06:49 +08:00
{
2018-12-30 18:00:05 +08:00
switch ( moveDirection )
{
case Direction . down :
this . SetMovingDown ( Move ) ;
break ;
case Direction . left :
this . SetMovingLeft ( Move ) ;
break ;
case Direction . up :
this . SetMovingUp ( Move ) ;
break ;
case Direction . right :
this . SetMovingRight ( Move ) ;
break ;
}
2018-03-19 07:06:49 +08:00
this . MovePosition ( time , viewport , currentLocation ) ;
}
2018-12-30 18:00:05 +08:00
/// <summary>USed to move the npc if the character renderer is null.</summary>
2018-03-19 07:06:49 +08:00
public virtual void NonModularMovement ( GameTime time , xTile . Dimensions . Rectangle viewport , GameLocation location )
{
2018-12-30 18:00:05 +08:00
base . MovePosition ( time , viewport , this . currentLocation ) ;
2018-03-19 07:06:49 +08:00
}
2018-12-30 18:00:05 +08:00
/// <summary>Used to determine if the npc can move past the next location.</summary>
2018-03-19 07:06:49 +08:00
public virtual bool canMovePastNextLocation ( xTile . Dimensions . Rectangle viewport )
{
//Up
2018-12-30 18:00:05 +08:00
if ( ! this . currentLocation . isTilePassable ( this . nextPosition ( 0 ) , viewport ) | | ! this . willDestroyObjectsUnderfoot )
2018-03-19 07:06:49 +08:00
return false ;
2018-12-30 18:00:05 +08:00
2018-03-19 07:06:49 +08:00
//Right
2018-12-30 18:00:05 +08:00
if ( ! this . currentLocation . isTilePassable ( this . nextPosition ( 1 ) , viewport ) | | ! this . willDestroyObjectsUnderfoot )
2018-03-19 07:06:49 +08:00
return false ;
2018-12-30 18:00:05 +08:00
2018-03-19 07:06:49 +08:00
//Down
2018-12-30 18:00:05 +08:00
if ( ! this . currentLocation . isTilePassable ( this . nextPosition ( 2 ) , viewport ) | | ! this . willDestroyObjectsUnderfoot )
2018-03-19 07:06:49 +08:00
return false ;
2018-12-30 18:00:05 +08:00
2018-03-19 07:06:49 +08:00
//Left
2018-12-30 18:00:05 +08:00
if ( ! this . currentLocation . isTilePassable ( this . nextPosition ( 3 ) , viewport ) | | ! this . willDestroyObjectsUnderfoot )
2018-03-19 07:06:49 +08:00
return false ;
2018-12-30 18:00:05 +08:00
2018-03-19 07:06:49 +08:00
return true ;
}
2018-12-30 18:00:05 +08:00
/// <summary>Used to move the npc if the character renderer is valid. Handles animating all of the sprites associated with the renderer.</summary>
2018-03-19 07:06:49 +08:00
public virtual void ModularMovement ( GameTime time , xTile . Dimensions . Rectangle viewport , GameLocation location , float interval = 1000f )
{
this . characterRenderer . setAnimation ( AnimationKeys . walkingKey ) ;
2018-12-30 18:00:05 +08:00
if ( ! this . canMovePastNextLocation ( viewport ) )
2018-03-19 07:06:49 +08:00
{
this . Halt ( ) ;
return ;
}
2018-02-24 15:40:34 +08:00
if ( this . GetType ( ) = = typeof ( FarmAnimal ) )
this . willDestroyObjectsUnderfoot = false ;
2018-12-30 18:00:05 +08:00
if ( this . xVelocity ! = 0.0 | | this . yVelocity ! = 0.0 )
2018-02-24 15:40:34 +08:00
{
2018-12-30 18:00:05 +08:00
var boundingBox = this . GetBoundingBox ( ) ;
2018-02-24 15:40:34 +08:00
boundingBox . X + = ( int ) this . xVelocity ;
boundingBox . Y - = ( int ) this . yVelocity ;
2018-12-30 18:00:05 +08:00
if ( this . currentLocation = = null | | ! this . currentLocation . isCollidingPosition ( boundingBox , viewport , false , 0 , false , this ) )
2018-02-24 15:40:34 +08:00
{
this . position . X + = this . xVelocity ;
this . position . Y - = this . yVelocity ;
}
2018-12-30 18:00:05 +08:00
this . xVelocity = ( int ) ( this . xVelocity - this . xVelocity / 2.0 ) ;
this . yVelocity = ( int ) ( this . yVelocity - this . yVelocity / 2.0 ) ;
2018-02-24 15:40:34 +08:00
}
else if ( this . moveUp )
{
2018-12-30 18:00:05 +08:00
if ( this . currentLocation = = null | | ! this . currentLocation . isCollidingPosition ( this . nextPosition ( 0 ) , viewport , false , 0 , false , this ) | | this . isCharging )
2018-02-24 15:40:34 +08:00
{
2018-12-30 18:00:05 +08:00
this . position . Y - = this . speed + this . addedSpeed ;
2018-02-24 15:40:34 +08:00
if ( ! this . ignoreMovementAnimation )
{
2018-03-19 07:06:49 +08:00
this . spriteInformation . setUp ( this ) ;
2018-12-30 18:00:05 +08:00
this . characterRenderer . Animate ( interval ) ;
2018-03-19 07:06:49 +08:00
//this.sprite.AnimateUp(time, (this.speed - 2 + this.addedSpeed) * -25, Utility.isOnScreen(this.getTileLocationPoint(), 1, currentLocation) ? "Cowboy_Footstep" : "");
2018-02-24 15:40:34 +08:00
this . faceDirection ( 0 ) ;
}
}
2018-12-30 18:00:05 +08:00
else if ( ! this . currentLocation . isTilePassable ( this . nextPosition ( 0 ) , viewport ) | | ! this . willDestroyObjectsUnderfoot )
2018-02-24 15:40:34 +08:00
this . Halt ( ) ;
else if ( this . willDestroyObjectsUnderfoot )
{
2018-12-30 18:00:05 +08:00
Vector2 vector2 = new Vector2 ( this . getStandingX ( ) / Game1 . tileSize , this . getStandingY ( ) / Game1 . tileSize - 1 ) ;
if ( this . currentLocation . characterDestroyObjectWithinRectangle ( this . nextPosition ( 0 ) , true ) )
2018-02-24 15:40:34 +08:00
{
2018-12-30 18:00:05 +08:00
this . doEmote ( 12 ) ;
this . position . Y - = this . speed + this . addedSpeed ;
2018-02-24 15:40:34 +08:00
}
else
this . blockedInterval = this . blockedInterval + time . ElapsedGameTime . Milliseconds ;
}
}
else if ( this . moveRight )
{
2018-12-30 18:00:05 +08:00
if ( this . currentLocation = = null | | ! this . currentLocation . isCollidingPosition ( this . nextPosition ( 1 ) , viewport , false , 0 , false , this ) | | this . isCharging )
2018-02-24 15:40:34 +08:00
{
2018-12-30 18:00:05 +08:00
this . position . X + = this . speed + this . addedSpeed ;
2018-02-24 15:40:34 +08:00
if ( ! this . ignoreMovementAnimation )
{
2018-03-19 07:06:49 +08:00
this . spriteInformation . setRight ( this ) ;
2018-12-30 18:00:05 +08:00
this . characterRenderer . Animate ( interval ) ;
2018-03-19 07:06:49 +08:00
//this.spriteInformation.sprite.Animate(time, 0, 3, 1f);
//this.sprite.AnimateRight(time, (this.speed - 2 + this.addedSpeed) * -25, Utility.isOnScreen(this.getTileLocationPoint(), 1, currentLocation) ? "Cowboy_Footstep" : "");
2018-02-24 15:40:34 +08:00
this . faceDirection ( 1 ) ;
}
}
2018-12-30 18:00:05 +08:00
else if ( ! this . currentLocation . isTilePassable ( this . nextPosition ( 1 ) , viewport ) | | ! this . willDestroyObjectsUnderfoot )
2018-02-24 15:40:34 +08:00
this . Halt ( ) ;
else if ( this . willDestroyObjectsUnderfoot )
{
2018-12-30 18:00:05 +08:00
Vector2 vector2 = new Vector2 ( this . getStandingX ( ) / Game1 . tileSize + 1 , this . getStandingY ( ) / Game1 . tileSize ) ;
if ( this . currentLocation . characterDestroyObjectWithinRectangle ( this . nextPosition ( 1 ) , true ) )
2018-02-24 15:40:34 +08:00
{
2018-12-30 18:00:05 +08:00
this . doEmote ( 12 ) ;
this . position . X + = this . speed + this . addedSpeed ;
2018-02-24 15:40:34 +08:00
}
else
this . blockedInterval = this . blockedInterval + time . ElapsedGameTime . Milliseconds ;
}
}
else if ( this . moveDown )
{
2018-12-30 18:00:05 +08:00
if ( this . currentLocation = = null | | ! this . currentLocation . isCollidingPosition ( this . nextPosition ( 2 ) , viewport , false , 0 , false , this ) | | this . isCharging )
2018-02-24 15:40:34 +08:00
{
2018-12-30 18:00:05 +08:00
this . position . Y + = this . speed + this . addedSpeed ;
2018-02-24 15:40:34 +08:00
if ( ! this . ignoreMovementAnimation )
{
2018-03-19 07:06:49 +08:00
this . spriteInformation . setDown ( this ) ;
2018-12-30 18:00:05 +08:00
this . characterRenderer . Animate ( interval ) ;
2018-03-19 07:06:49 +08:00
//this.spriteInformation.sprite.Animate(time, 0, 3, 1f);
//this.sprite.AnimateDown(time, (this.speed - 2 + this.addedSpeed) * -25, Utility.isOnScreen(this.getTileLocationPoint(), 1, currentLocation) ? "Cowboy_Footstep" : "");
2018-02-24 15:40:34 +08:00
this . faceDirection ( 2 ) ;
}
}
2018-12-30 18:00:05 +08:00
else if ( ! this . currentLocation . isTilePassable ( this . nextPosition ( 2 ) , viewport ) | | ! this . willDestroyObjectsUnderfoot )
2018-02-24 15:40:34 +08:00
this . Halt ( ) ;
else if ( this . willDestroyObjectsUnderfoot )
{
2018-12-30 18:00:05 +08:00
Vector2 vector2 = new Vector2 ( this . getStandingX ( ) / Game1 . tileSize , this . getStandingY ( ) / Game1 . tileSize + 1 ) ;
if ( this . currentLocation . characterDestroyObjectWithinRectangle ( this . nextPosition ( 2 ) , true ) )
2018-02-24 15:40:34 +08:00
{
2018-12-30 18:00:05 +08:00
this . doEmote ( 12 ) ;
this . position . Y + = this . speed + this . addedSpeed ;
2018-02-24 15:40:34 +08:00
}
else
this . blockedInterval = this . blockedInterval + time . ElapsedGameTime . Milliseconds ;
}
}
else if ( this . moveLeft )
{
2018-12-30 18:00:05 +08:00
if ( this . currentLocation = = null | | ! this . currentLocation . isCollidingPosition ( this . nextPosition ( 3 ) , viewport , false , 0 , false , this ) | | this . isCharging )
2018-02-24 15:40:34 +08:00
{
2018-12-30 18:00:05 +08:00
this . position . X - = this . speed + this . addedSpeed ;
2018-02-24 15:40:34 +08:00
if ( ! this . ignoreMovementAnimation )
{
2018-03-19 07:06:49 +08:00
this . spriteInformation . setLeft ( this ) ;
2018-12-30 18:00:05 +08:00
this . characterRenderer . Animate ( interval ) ;
2018-03-19 07:06:49 +08:00
//this.spriteInformation.sprite.Animate(time, 0, 3, 1f);
//this.sprite.AnimateLeft(time, (this.speed - 2 + this.addedSpeed) * -25, Utility.isOnScreen(this.getTileLocationPoint(), 1, currentLocation) ? "Cowboy_Footstep" : "");
2018-02-24 15:40:34 +08:00
this . faceDirection ( 3 ) ;
}
}
2018-12-30 18:00:05 +08:00
else if ( ! this . currentLocation . isTilePassable ( this . nextPosition ( 3 ) , viewport ) | | ! this . willDestroyObjectsUnderfoot )
2018-02-24 15:40:34 +08:00
this . Halt ( ) ;
else if ( this . willDestroyObjectsUnderfoot )
{
2018-12-30 18:00:05 +08:00
Vector2 vector2 = new Vector2 ( this . getStandingX ( ) / Game1 . tileSize - 1 , this . getStandingY ( ) / Game1 . tileSize ) ;
if ( this . currentLocation . characterDestroyObjectWithinRectangle ( this . nextPosition ( 3 ) , true ) )
2018-02-24 15:40:34 +08:00
{
2018-12-30 18:00:05 +08:00
this . doEmote ( 12 ) ;
this . position . X - = this . speed + this . addedSpeed ;
2018-02-24 15:40:34 +08:00
}
else
this . blockedInterval = this . blockedInterval + time . ElapsedGameTime . Milliseconds ;
}
}
2018-12-30 18:00:05 +08:00
if ( this . blockedInterval > = 3000 & & this . blockedInterval < = 3750.0 & & ! Game1 . eventUp )
2018-02-24 15:40:34 +08:00
{
2018-12-30 18:00:05 +08:00
this . doEmote ( Game1 . random . NextDouble ( ) < 0.5 ? 8 : 40 ) ;
2018-02-24 15:40:34 +08:00
this . blockedInterval = 3750 ;
}
else
{
if ( this . blockedInterval < 5000 )
return ;
this . speed = 4 ;
this . isCharging = true ;
this . blockedInterval = 0 ;
}
}
2018-12-30 18:00:05 +08:00
/// <summary>Used to halt the npc sprite. Sets the npc's animation to the standing animation if the character renderer is not null.</summary>
2018-03-19 07:06:49 +08:00
public override void Halt ( )
{
2018-12-30 18:00:05 +08:00
this . characterRenderer ? . setAnimation ( AnimationKeys . standingKey ) ;
2018-03-19 07:06:49 +08:00
base . Halt ( ) ;
}
2018-12-30 18:00:05 +08:00
/// <summary>Pathfinding code.</summary>
public virtual void routeEndAnimationFinished ( Farmer who )
2018-02-24 15:40:34 +08:00
{
2018-05-01 09:21:31 +08:00
this . doingEndOfRouteAnimation . Value = false ;
2018-02-24 15:40:34 +08:00
this . freezeMotion = false ;
2018-05-01 09:21:31 +08:00
this . Sprite . SpriteHeight = 32 ;
this . Sprite . StopAnimation ( ) ;
this . endOfRouteMessage . Value = ( string ) null ;
2018-02-24 15:40:34 +08:00
this . isCharging = false ;
this . speed = 2 ;
this . addedSpeed = 0 ;
2018-05-01 09:21:31 +08:00
this . goingToDoEndOfRouteAnimation . Value = false ;
2018-02-24 17:04:35 +08:00
if ( ! this . IsWalkingInSquare )
2018-02-24 15:40:34 +08:00
return ;
this . returningToEndPoint = true ;
this . timeAfterSquare = Game1 . timeOfDay ;
}
2018-12-30 18:00:05 +08:00
/// <summary>Pathfinding code.</summary>
public virtual void doAnimationAtEndOfScheduleRoute ( Character c , GameLocation l ) { }
2018-02-24 15:40:34 +08:00
2018-12-30 18:00:05 +08:00
/// <summary>Pathfinding code.</summary>
2018-02-24 15:40:34 +08:00
public virtual void startRouteBehavior ( string behaviorName )
{
if ( behaviorName . Length > 0 & & ( int ) behaviorName [ 0 ] = = 34 )
2018-05-01 09:21:31 +08:00
this . endOfRouteMessage . Value = behaviorName . Replace ( "\"" , "" ) ;
2018-02-24 15:40:34 +08:00
else
{
if ( behaviorName . Contains ( "square_" ) )
{
this . lastCrossroad = new Microsoft . Xna . Framework . Rectangle ( this . getTileX ( ) * Game1 . tileSize , this . getTileY ( ) * Game1 . tileSize , Game1 . tileSize , Game1 . tileSize ) ;
string [ ] strArray = behaviorName . Split ( '_' ) ;
this . walkInSquare ( Convert . ToInt32 ( strArray [ 1 ] ) , Convert . ToInt32 ( strArray [ 2 ] ) , 6000 ) ;
this . squareMovementFacingPreference = strArray . Length < = 3 ? - 1 : Convert . ToInt32 ( strArray [ 3 ] ) ;
}
else
{
2018-12-30 18:00:05 +08:00
Utility . getGameLocationOfCharacter ( this ) . temporarySprites . Add ( new TemporaryAnimatedSprite ( "LooseSprites\\Cursors" , new Microsoft . Xna . Framework . Rectangle ( 167 , 1714 , 19 , 14 ) , 100f , 3 , 999999 , new Vector2 ( 2f , 3f ) * ( float ) Game1 . tileSize + new Vector2 ( 7f , 12f ) * ( float ) Game1 . pixelZoom , false , false , 0.0002f , 0.0f , Color . White , ( float ) Game1 . pixelZoom , 0.0f , 0.0f , 0.0f )
2018-02-24 15:40:34 +08:00
{
id = 688f
} ) ;
2018-12-30 18:00:05 +08:00
this . doEmote ( 52 ) ;
2018-02-24 15:40:34 +08:00
}
}
}
2018-02-24 17:04:35 +08:00
2018-12-30 18:00:05 +08:00
/// <summary>Occurs when the npc gets hit by the player.</summary>
2018-02-24 17:04:35 +08:00
public new void getHitByPlayer ( StardewValley . Farmer who , GameLocation location )
2018-02-24 15:40:34 +08:00
{
2018-12-30 18:00:05 +08:00
this . doEmote ( 12 ) ;
2018-02-24 15:40:34 +08:00
if ( who = = null )
{
if ( Game1 . IsMultiplayer )
return ;
who = Game1 . player ;
}
2018-05-01 09:21:31 +08:00
if ( who . friendshipData . ContainsKey ( this . Name ) )
2018-02-24 15:40:34 +08:00
{
2018-12-30 18:00:05 +08:00
who . friendshipData . TryGetValue ( this . Name , out Friendship f ) ;
2018-05-01 09:21:31 +08:00
f . Points - = 30 ;
2018-02-24 15:40:34 +08:00
if ( who . IsMainPlayer )
{
this . CurrentDialogue . Clear ( ) ;
2018-02-24 17:04:35 +08:00
//this.CurrentDialogue.Push(new StardewValley.Dialogue(Game1.random.NextDouble() < 0.5 ? Game1.LoadStringByGender(this.gender, "Strings\\StringsFromCSFiles:NPC.cs.4293") : Game1.content.LoadString("Strings\\StringsFromCSFiles:NPC.cs.4294"), this));
2018-02-24 15:40:34 +08:00
}
2018-02-24 17:04:35 +08:00
//location.debris.Add(new Debris(this.sprite.Texture, Game1.random.Next(3, 8), new Vector2((float)this.GetBoundingBox().Center.X, (float)this.GetBoundingBox().Center.Y)));
2018-02-24 15:40:34 +08:00
}
2018-05-01 09:21:31 +08:00
if ( this . Name . Equals ( "Bouncer" ) )
2018-02-24 15:40:34 +08:00
Game1 . playSound ( "crafting" ) ;
else
Game1 . playSound ( "hitEnemy" ) ;
}
//ERROR NEED FIXING
public override void dayUpdate ( int dayOfMonth )
{
if ( this . currentLocation ! = null )
2018-12-30 18:00:05 +08:00
Game1 . warpCharacter ( this , this . DefaultMap , this . DefaultPosition / Game1 . tileSize ) ;
2018-05-01 09:21:31 +08:00
Game1 . player . mailReceived . Remove ( this . Name ) ;
Game1 . player . mailReceived . Remove ( this . Name + "Cooking" ) ;
this . doingEndOfRouteAnimation . Value = false ;
2018-02-24 15:40:34 +08:00
this . Halt ( ) ;
this . hasBeenKissedToday = false ;
this . faceTowardFarmer = false ;
this . faceTowardFarmerTimer = 0 ;
2018-05-01 09:21:31 +08:00
this . drawOffset . Value = Vector2 . Zero ;
2018-02-24 15:40:34 +08:00
this . hasSaidAfternoonDialogue = false ;
this . ignoreScheduleToday = false ;
this . Halt ( ) ;
2018-12-30 18:00:05 +08:00
this . controller = null ;
this . temporaryController = null ;
this . DirectionsToNewLocation = null ;
2018-02-24 15:40:34 +08:00
this . faceDirection ( this . DefaultFacingDirection ) ;
this . scheduleTimeToTry = 9999999 ;
2018-02-24 17:04:35 +08:00
this . previousEndPoint = new Point ( ( int ) this . DefaultPosition . X / Game1 . tileSize , ( int ) this . DefaultPosition . Y / Game1 . tileSize ) ;
this . IsWalkingInSquare = false ;
2018-02-24 15:40:34 +08:00
this . returningToEndPoint = false ;
2018-12-30 18:00:05 +08:00
this . lastCrossroad = Rectangle . Empty ;
2018-02-24 15:40:34 +08:00
if ( this . isVillager ( ) )
this . Schedule = this . getSchedule ( dayOfMonth ) ;
2018-12-30 18:00:05 +08:00
this . endOfRouteMessage . Value = null ;
2018-02-24 15:40:34 +08:00
bool flag = Utility . isFestivalDay ( dayOfMonth , Game1 . currentSeason ) ;
if ( ! this . isMarried ( ) )
return ;
2018-06-09 02:40:23 +08:00
this . marriageDuties ( ) ;
2018-05-01 09:21:31 +08:00
//Friendship f=Game1.player.GetSpouseFriendship();
//this.daysMarried = this.daysMarried + 1;
2018-02-24 15:40:34 +08:00
}
2018-12-30 18:00:05 +08:00
/// <summary>Does effectively nothing.</summary>
public new void setUpForOutdoorPatioActivity ( ) { }
2018-02-24 15:40:34 +08:00
2018-12-30 18:00:05 +08:00
/// <summary>Used to draw the npc with the custom renderer.</summary>
2018-02-24 17:04:35 +08:00
public virtual void drawModular ( SpriteBatch b , float alpha = 1f )
2018-02-24 15:40:34 +08:00
{
2018-05-01 09:21:31 +08:00
if ( this . characterRenderer = = null | | this . IsInvisible | | ! Utility . isOnScreen ( this . position , 2 * Game1 . tileSize ) )
2018-02-24 15:40:34 +08:00
return ;
//Checks if the npc is swimming. If not draw it's default graphic. Do characters aside from Farmer and Penny Swim???
2018-05-01 09:21:31 +08:00
if ( this . swimming . Value )
2018-02-24 15:40:34 +08:00
{
this . characterRenderer . setAnimation ( AnimationKeys . swimmingKey ) ;
this . characterRenderer . setDirection ( this . facingDirection ) ;
2018-12-30 18:00:05 +08:00
this . characterRenderer . draw ( b , this , this . getLocalPosition ( Game1 . viewport ) + new Vector2 ( ( float ) ( Game1 . tileSize / 2 ) , ( float ) ( Game1 . tileSize + Game1 . tileSize / 4 + this . yJumpOffset * 2 ) ) + ( this . shakeTimer > 0 ? new Vector2 ( ( float ) Game1 . random . Next ( - 1 , 2 ) , ( float ) Game1 . random . Next ( - 1 , 2 ) ) : Vector2 . Zero ) - new Vector2 ( 0.0f , this . yOffset ) , new Microsoft . Xna . Framework . Rectangle ? ( new Microsoft . Xna . Framework . Rectangle ( this . Sprite . SourceRect . X , this . Sprite . SourceRect . Y , this . Sprite . SourceRect . Width , this . Sprite . SourceRect . Height / 2 - ( int ) ( ( double ) this . yOffset / ( double ) Game1 . pixelZoom ) ) ) , Color . White , this . rotation , new Vector2 ( ( float ) ( Game1 . tileSize / 2 ) , ( float ) ( Game1 . tileSize * 3 / 2 ) ) / 4f , Math . Max ( 0.2f , this . Scale ) * ( float ) Game1 . pixelZoom , this . flip ? SpriteEffects . FlipHorizontally : SpriteEffects . None , Math . Max ( 0.0f , ( float ) this . getStandingY ( ) / 10000f ) ) ;
2018-02-24 15:40:34 +08:00
//Vector2 localPosition = this.getLocalPosition(Game1.viewport);
//b.Draw(Game1.staminaRect, new Microsoft.Xna.Framework.Rectangle((int)localPosition.X + (int)this.yOffset + Game1.pixelZoom * 2, (int)localPosition.Y - 32 * Game1.pixelZoom + this.sprite.SourceRect.Height * Game1.pixelZoom + Game1.tileSize * 3 / 4 + this.yJumpOffset * 2 - (int)this.yOffset, this.sprite.SourceRect.Width * Game1.pixelZoom - (int)this.yOffset * 2 - Game1.pixelZoom * 4, Game1.pixelZoom), new Microsoft.Xna.Framework.Rectangle?(Game1.staminaRect.Bounds), Color.White * 0.75f, 0.0f, Vector2.Zero, SpriteEffects.None, (float)((double)this.getStandingY() / 10000.0 + 1.0 / 1000.0));
}
else
{
2018-03-17 19:04:04 +08:00
//FIX THIS LINE WITH LAYER DEPTH!!!
2018-03-17 19:18:35 +08:00
//Shadow???
2018-03-18 12:49:22 +08:00
//this.characterRenderer.draw(b,this, this.getLocalPosition(Game1.viewport) + new Vector2((float)(this.sprite.spriteWidth * Game1.pixelZoom / 2), (float)(this.GetBoundingBox().Height / 2)) + (this.shakeTimer > 0 ? new Vector2((float)Game1.random.Next(-1, 2), (float)Game1.random.Next(-1, 2)) : Vector2.Zero), new Microsoft.Xna.Framework.Rectangle?(this.Sprite.SourceRect), Color.White * alpha, this.rotation, new Vector2((float)(this.sprite.spriteWidth / 2), (float)((double)this.sprite.spriteHeight * 3.0 / 4.0)), Math.Max(0.2f, this.scale) * (float)Game1.pixelZoom, this.flip || this.sprite.currentAnimation != null && this.sprite.currentAnimation[this.sprite.currentAnimationIndex].flip ? SpriteEffects.FlipHorizontally : SpriteEffects.None, Math.Max(0.0f, this.drawOnTop ? 0.991f : (float)this.getStandingY() / 10000f));
2018-02-24 15:40:34 +08:00
}
//If the npc breathes then this code is ran.
2018-05-01 09:21:31 +08:00
if ( this . Breather & & this . shakeTimer < = 0 & & ( ! this . swimming . Value & & this . Sprite . CurrentFrame < 16 ) & & ! this . farmerPassesThrough )
{
Microsoft . Xna . Framework . Rectangle sourceRect = this . Sprite . SourceRect ;
sourceRect . Y + = this . Sprite . SpriteHeight / 2 + this . Sprite . SpriteHeight / 32 ;
sourceRect . Height = this . Sprite . SpriteHeight / 4 ;
sourceRect . X + = this . Sprite . SpriteWidth / 4 ;
sourceRect . Width = this . Sprite . SpriteWidth / 2 ;
Vector2 vector2 = new Vector2 ( ( float ) ( this . Sprite . SpriteWidth * Game1 . pixelZoom / 2 ) , ( float ) ( Game1 . tileSize / 8 ) ) ;
if ( this . Age = = 2 )
2018-02-24 15:40:34 +08:00
{
2018-05-01 09:21:31 +08:00
sourceRect . Y + = this . Sprite . SpriteHeight / 6 + 1 ;
2018-02-24 15:40:34 +08:00
sourceRect . Height / = 2 ;
2018-05-01 09:21:31 +08:00
vector2 . Y + = ( float ) ( this . Sprite . SpriteHeight / 8 * Game1 . pixelZoom ) ;
2018-02-24 15:40:34 +08:00
}
2018-05-01 09:21:31 +08:00
else if ( this . Gender = = 1 )
2018-02-24 15:40:34 +08:00
{
+ + sourceRect . Y ;
vector2 . Y - = ( float ) Game1 . pixelZoom ;
sourceRect . Height / = 2 ;
}
2018-03-17 19:18:35 +08:00
//The actual character drawing to the screen?
2018-12-30 18:00:05 +08:00
this . characterRenderer . draw ( b , this , this . getLocalPosition ( Game1 . viewport ) + ( this . shakeTimer > 0 ? new Vector2 ( ( float ) Game1 . random . Next ( - 1 , 2 ) , ( float ) Game1 . random . Next ( - 1 , 2 ) ) : Vector2 . Zero ) , new Microsoft . Xna . Framework . Rectangle ? ( sourceRect ) , Color . White * alpha , this . rotation , Vector2 . Zero , Math . Max ( 0.2f , this . Scale ) , this . flip ? SpriteEffects . FlipHorizontally : SpriteEffects . None , Math . Max ( 0.0f , this . drawOnTop ? 0.992f : ( float ) ( ( double ) this . getStandingY ( ) / 10000.0 + 1.0 / 1000.0 ) ) ) ;
2018-03-17 19:18:35 +08:00
//this.characterRenderer.draw(b,this, this.getLocalPosition(Game1.viewport) + vector2 + (this.shakeTimer > 0 ? new Vector2((float)Game1.random.Next(-1, 2), (float)Game1.random.Next(-1, 2)) : Vector2.Zero), new Microsoft.Xna.Framework.Rectangle?(sourceRect), Color.White * alpha, this.rotation, new Vector2((float)(sourceRect.Width / 2), (float)(sourceRect.Height / 2 + 1)), Math.Max(0.2f, this.scale) * (float)Game1.pixelZoom + num, this.flip ? SpriteEffects.FlipHorizontally : SpriteEffects.None, Math.Max(0.0f, this.drawOnTop ? 0.992f : (float)((double)this.getStandingY() / 10000.0 + 1.0 / 1000.0)));
2018-03-18 12:49:22 +08:00
//this.characterRenderer.draw(b, this, this.getLocalPosition(Game1.viewport) + vector2 + (this.shakeTimer > 0 ? new Vector2((float)Game1.random.Next(-1, 2), (float)Game1.random.Next(-1, 2)) : Vector2.Zero), new Microsoft.Xna.Framework.Rectangle?(sourceRect), Color.White * alpha, this.rotation, new Vector2((float)(sourceRect.Width / 2), (float)(sourceRect.Height / 2 + 1)), Math.Max(0.2f, this.scale) * (float)Game1.pixelZoom + num, this.flip ? SpriteEffects.FlipHorizontally : SpriteEffects.None, .99f);
2018-02-24 15:40:34 +08:00
}
2018-03-18 18:20:06 +08:00
else
{
//float num = Math.Max(0.0f, (float)(Math.Ceiling(Math.Sin(Game1.currentGameTime.TotalGameTime.TotalMilliseconds / 600.0 + (double)this.DefaultPosition.X * 20.0)) / 4.0));
2018-05-01 09:21:31 +08:00
this . characterRenderer . draw ( b , this , this . getLocalPosition ( Game1 . viewport ) + ( this . shakeTimer > 0 ? new Vector2 ( ( float ) Game1 . random . Next ( - 1 , 2 ) , ( float ) Game1 . random . Next ( - 1 , 2 ) ) : Vector2 . Zero ) , new Microsoft . Xna . Framework . Rectangle ? ( new Microsoft . Xna . Framework . Rectangle ( ) ) , Color . White * alpha , this . rotation , Vector2 . Zero , Math . Max ( 0.2f , this . Scale ) , this . flip ? SpriteEffects . FlipHorizontally : SpriteEffects . None , Math . Max ( 0.0f , this . drawOnTop ? 0.992f : ( float ) ( ( double ) this . getStandingY ( ) / 10000.0 + 1.0 / 1000.0 ) ) ) ;
2018-03-18 18:20:06 +08:00
}
2018-02-24 15:40:34 +08:00
//Checks if the npc is glowing.
if ( this . isGlowing )
2018-12-30 18:00:05 +08:00
this . characterRenderer . draw ( b , this , this . getLocalPosition ( Game1 . viewport ) + new Vector2 ( ( float ) ( this . Sprite . SpriteWidth * Game1 . pixelZoom / 2 ) , ( float ) ( this . GetBoundingBox ( ) . Height / 2 ) ) + ( this . shakeTimer > 0 ? new Vector2 ( ( float ) Game1 . random . Next ( - 1 , 2 ) , ( float ) Game1 . random . Next ( - 1 , 2 ) ) : Vector2 . Zero ) , new Microsoft . Xna . Framework . Rectangle ? ( this . Sprite . SourceRect ) , this . glowingColor * this . glowingTransparency , this . rotation , new Vector2 ( ( float ) ( this . Sprite . SpriteWidth / 2 ) , ( float ) ( ( double ) this . Sprite . SpriteHeight * 3.0 / 4.0 ) ) , Math . Max ( 0.2f , this . Scale ) * 4f , this . flip ? SpriteEffects . FlipHorizontally : SpriteEffects . None , Math . Max ( 0.0f , this . drawOnTop ? 0.99f : ( float ) ( ( double ) this . getStandingY ( ) / 10000.0 + 1.0 / 1000.0 ) ) ) ;
2018-02-24 15:40:34 +08:00
//This code runs if the npc is emoting.
if ( ! this . IsEmoting | | Game1 . eventUp )
return ;
Vector2 localPosition1 = this . getLocalPosition ( Game1 . viewport ) ;
2018-05-01 09:21:31 +08:00
localPosition1 . Y - = ( float ) ( Game1 . tileSize / 2 + this . Sprite . SpriteHeight * Game1 . pixelZoom ) ;
2018-02-24 15:40:34 +08:00
b . Draw ( Game1 . emoteSpriteSheet , localPosition1 , new Microsoft . Xna . Framework . Rectangle ? ( new Microsoft . Xna . Framework . Rectangle ( this . CurrentEmoteIndex * 16 % Game1 . emoteSpriteSheet . Width , this . CurrentEmoteIndex * 16 / Game1 . emoteSpriteSheet . Width * 16 , 16 , 16 ) ) , Color . White , 0.0f , Vector2 . Zero , ( float ) Game1 . pixelZoom , SpriteEffects . None , ( float ) this . getStandingY ( ) / 10000f ) ;
}
2018-02-24 17:04:35 +08:00
2018-12-30 18:00:05 +08:00
/// <summary>Used to draw the sprite without the modular npc renderer</summary>
2018-03-18 12:49:22 +08:00
/// <param name="b"></param>
/// <param name="alpha"></param>
2018-02-24 17:04:35 +08:00
public virtual void drawNonModularSprite ( SpriteBatch b , float alpha = 1f )
{
2018-05-01 09:21:31 +08:00
if ( this . Sprite = = null | | this . IsInvisible | | ! Utility . isOnScreen ( this . position , 2 * Game1 . tileSize ) )
2018-02-24 17:04:35 +08:00
return ;
2018-03-18 12:49:22 +08:00
//Swimming just has a height difference on the sprite.
2018-05-01 09:21:31 +08:00
if ( this . swimming . Value )
2018-02-24 17:04:35 +08:00
{
2018-05-01 09:21:31 +08:00
b . Draw ( this . Sprite . Texture , this . getLocalPosition ( Game1 . viewport ) + new Vector2 ( ( float ) ( Game1 . tileSize / 2 ) , ( float ) ( Game1 . tileSize + Game1 . tileSize / 4 + this . yJumpOffset * 2 ) ) + ( this . shakeTimer > 0 ? new Vector2 ( ( float ) Game1 . random . Next ( - 1 , 2 ) , ( float ) Game1 . random . Next ( - 1 , 2 ) ) : Vector2 . Zero ) - new Vector2 ( 0.0f , this . yOffset ) , new Microsoft . Xna . Framework . Rectangle ? ( new Microsoft . Xna . Framework . Rectangle ( this . Sprite . SourceRect . X , this . Sprite . SourceRect . Y , this . Sprite . SourceRect . Width , this . Sprite . SourceRect . Height / 2 - ( int ) ( ( double ) this . yOffset / ( double ) Game1 . pixelZoom ) ) ) , Color . White , this . rotation , new Vector2 ( ( float ) ( Game1 . tileSize / 2 ) , ( float ) ( Game1 . tileSize * 3 / 2 ) ) / 4f , Math . Max ( 0.2f , this . Scale ) * ( float ) Game1 . pixelZoom , this . flip ? SpriteEffects . FlipHorizontally : SpriteEffects . None , Math . Max ( 0.0f , this . drawOnTop ? 0.991f : ( float ) this . getStandingY ( ) / 10000f ) ) ;
2018-02-24 17:04:35 +08:00
Vector2 localPosition = this . getLocalPosition ( Game1 . viewport ) ;
2018-02-24 17:36:41 +08:00
//b.Draw(Game1.staminaRect, new Microsoft.Xna.Framework.Rectangle((int)localPosition.X + (int)this.yOffset + Game1.pixelZoom * 2, (int)localPosition.Y - 32 * Game1.pixelZoom + this.sprite.SourceRect.Height * Game1.pixelZoom + Game1.tileSize * 3 / 4 + this.yJumpOffset * 2 - (int)this.yOffset, this.sprite.SourceRect.Width * Game1.pixelZoom - (int)this.yOffset * 2 - Game1.pixelZoom * 4, Game1.pixelZoom), new Microsoft.Xna.Framework.Rectangle?(Game1.staminaRect.Bounds), Color.White * 0.75f, 0.0f, Vector2.Zero, SpriteEffects.None, (float)((double)this.getStandingY() / 10000.0 + 1.0 / 1000.0));
2018-02-24 17:04:35 +08:00
}
else
2018-05-01 09:21:31 +08:00
b . Draw ( this . Sprite . Texture , this . getLocalPosition ( Game1 . viewport ) + new Vector2 ( ( float ) ( this . Sprite . SpriteWidth * Game1 . pixelZoom / 2 ) , ( float ) ( this . GetBoundingBox ( ) . Height / 2 ) ) + ( this . shakeTimer > 0 ? new Vector2 ( ( float ) Game1 . random . Next ( - 1 , 2 ) , ( float ) Game1 . random . Next ( - 1 , 2 ) ) : Vector2 . Zero ) , new Microsoft . Xna . Framework . Rectangle ? ( this . Sprite . SourceRect ) , Color . White * alpha , this . rotation , new Vector2 ( ( float ) ( this . Sprite . SpriteWidth / 2 ) , ( float ) ( ( double ) this . Sprite . SpriteHeight * 3.0 / 4.0 ) ) , Math . Max ( 0.2f , this . Scale ) * ( float ) Game1 . pixelZoom , this . flip | | this . Sprite . currentAnimation ! = null & & this . Sprite . currentAnimation [ this . Sprite . currentAnimationIndex ] . flip ? SpriteEffects . FlipHorizontally : SpriteEffects . None , Math . Max ( 0.0f , this . drawOnTop ? 0.991f : ( float ) this . getStandingY ( ) / 10000f ) ) ;
if ( this . Breather & & this . shakeTimer < = 0 & & ( ! this . swimming . Value & & this . Sprite . CurrentFrame < 16 ) & & ! this . farmerPassesThrough )
{
Microsoft . Xna . Framework . Rectangle sourceRect = this . Sprite . SourceRect ;
sourceRect . Y + = this . Sprite . SpriteHeight / 2 + this . Sprite . SpriteHeight / 32 ;
sourceRect . Height = this . Sprite . SpriteHeight / 4 ;
sourceRect . X + = this . Sprite . SpriteWidth / 4 ;
sourceRect . Width = this . Sprite . SpriteWidth / 2 ;
Vector2 vector2 = new Vector2 ( ( float ) ( this . Sprite . SpriteWidth * Game1 . pixelZoom / 2 ) , ( float ) ( Game1 . tileSize / 8 ) ) ;
if ( this . Age = = 2 )
2018-02-24 17:04:35 +08:00
{
2018-05-01 09:21:31 +08:00
sourceRect . Y + = this . Sprite . SpriteHeight / 6 + 1 ;
2018-02-24 17:04:35 +08:00
sourceRect . Height / = 2 ;
2018-05-01 09:21:31 +08:00
vector2 . Y + = ( float ) ( this . Sprite . SpriteHeight / 8 * Game1 . pixelZoom ) ;
2018-02-24 17:04:35 +08:00
}
2018-05-01 09:21:31 +08:00
else if ( this . Gender = = 1 )
2018-02-24 17:04:35 +08:00
{
+ + sourceRect . Y ;
vector2 . Y - = ( float ) Game1 . pixelZoom ;
sourceRect . Height / = 2 ;
}
float num = Math . Max ( 0.0f , ( float ) ( Math . Ceiling ( Math . Sin ( Game1 . currentGameTime . TotalGameTime . TotalMilliseconds / 600.0 + ( double ) this . DefaultPosition . X * 20.0 ) ) / 4.0 ) ) ;
2018-02-24 17:36:41 +08:00
2018-05-01 09:21:31 +08:00
b . Draw ( this . Sprite . Texture , this . getLocalPosition ( Game1 . viewport ) + vector2 + ( this . shakeTimer > 0 ? new Vector2 ( ( float ) Game1 . random . Next ( - 1 , 2 ) , ( float ) Game1 . random . Next ( - 1 , 2 ) ) : Vector2 . Zero ) , new Microsoft . Xna . Framework . Rectangle ? ( sourceRect ) , Color . White * alpha , this . rotation , new Vector2 ( ( float ) ( sourceRect . Width / 2 ) , ( float ) ( sourceRect . Height / 2 + 1 ) ) , Math . Max ( 0.2f , this . Scale ) * ( float ) Game1 . pixelZoom + num , this . flip ? SpriteEffects . FlipHorizontally : SpriteEffects . None , Math . Max ( 0.0f , this . drawOnTop ? 0.992f : ( float ) ( ( double ) this . getStandingY ( ) / 10000.0 + 1.0 / 1000.0 ) ) ) ;
2018-02-24 17:04:35 +08:00
}
if ( this . isGlowing )
2018-05-01 09:21:31 +08:00
b . Draw ( this . Sprite . Texture , this . getLocalPosition ( Game1 . viewport ) + new Vector2 ( ( float ) ( this . Sprite . SpriteWidth * Game1 . pixelZoom / 2 ) , ( float ) ( this . GetBoundingBox ( ) . Height / 2 ) ) + ( this . shakeTimer > 0 ? new Vector2 ( ( float ) Game1 . random . Next ( - 1 , 2 ) , ( float ) Game1 . random . Next ( - 1 , 2 ) ) : Vector2 . Zero ) , new Microsoft . Xna . Framework . Rectangle ? ( this . Sprite . SourceRect ) , this . glowingColor * this . glowingTransparency , this . rotation , new Vector2 ( ( float ) ( this . Sprite . SpriteWidth / 2 ) , ( float ) ( ( double ) this . Sprite . SpriteHeight * 3.0 / 4.0 ) ) , Math . Max ( 0.2f , this . Scale ) * 4f , this . flip ? SpriteEffects . FlipHorizontally : SpriteEffects . None , Math . Max ( 0.0f , this . drawOnTop ? 0.99f : ( float ) ( ( double ) this . getStandingY ( ) / 10000.0 + 1.0 / 1000.0 ) ) ) ;
2018-02-24 17:04:35 +08:00
Vector2 localPosition1 = this . getLocalPosition ( Game1 . viewport ) ;
2018-05-01 09:21:31 +08:00
localPosition1 . Y - = ( float ) ( Game1 . tileSize / 2 + this . Sprite . SpriteHeight * Game1 . pixelZoom ) ;
2018-02-24 17:36:41 +08:00
//b.Draw(Game1.emoteSpriteSheet, localPosition1, new Microsoft.Xna.Framework.Rectangle?(new Microsoft.Xna.Framework.Rectangle(this.CurrentEmoteIndex * 16 % Game1.emoteSpriteSheet.Width, this.CurrentEmoteIndex * 16 / Game1.emoteSpriteSheet.Width * 16, 16, 16)), Color.White, 0.0f, Vector2.Zero, (float)Game1.pixelZoom, SpriteEffects.None, (float)this.getStandingY() / 10000f);
2018-02-24 17:04:35 +08:00
}
2018-12-30 18:00:05 +08:00
/// <summary>Basic draw functionality to checkn whether or not to draw the npc using it's default sprite or using a custom character renderer.</summary>
2018-03-19 07:06:49 +08:00
/// <param name="b"></param>
/// <param name="alpha"></param>
2018-02-24 17:04:35 +08:00
public override void draw ( SpriteBatch b , float alpha = 1f )
{
if ( this . characterRenderer = = null )
{
this . drawNonModularSprite ( b , alpha ) ;
}
else
{
this . drawModular ( b , alpha ) ;
}
}
2018-02-24 11:10:56 +08:00
}
}