diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
index f39547848..8634e9230 100644
--- a/.github/workflows/build-and-test.yml
+++ b/.github/workflows/build-and-test.yml
@@ -5,9 +5,9 @@ name: .NET Build and Test
on:
push:
- branches: [ "master" ]
+ branches: [ "master", "Yggdrasil/newContent0"]
pull_request:
- branches: [ "master" ]
+ branches: [ "master", "Yggdrasil/newContent0"]
jobs:
build-and-test:
diff --git a/Libraries/ModLiquidLib.dll b/Libraries/ModLiquidLib.dll
new file mode 100644
index 000000000..5cc5b7ac9
Binary files /dev/null and b/Libraries/ModLiquidLib.dll differ
diff --git a/Libraries/ModLiquidLib.xml b/Libraries/ModLiquidLib.xml
new file mode 100644
index 000000000..a17b6d58a
--- /dev/null
+++ b/Libraries/ModLiquidLib.xml
@@ -0,0 +1,1238 @@
+
+
+
+ ModLiquidLib
+
+
+
+ Whether or not this tile counts as a this liquid's source for crafting purposes.
+
+
+ The Item created when a bucket is used on a liquid selected
+
+
+ Whats Items a liquid can be absorbed by. Used for defining sponges.
+
+
+ Whether or not the NPC can spawn in the liquid specified. NOTE: only works for modded liquids and npcs
+
+
+ Whether or not the liquid uses the water loot pool when fished it. NOTE: this set does not effect/change Water, lava or honey and is mainly used for modded liquids.
+
+
+
+ This class allows you to modify the behavior of any liquid in the game, both vanilla and modded.
+
To use it, simply create a new class deriving from this one. Implementations will be registered automatically.
+
+
+
+
+ Allows you to draw things behind the liquid at the given coordinates. Return false to stop the game from drawing the liquid normally. Returns true by default.
+ This method is only called in "Color" and "White" lighting modes. Use for the other Lighting modes pre drawing
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+ The LiquidDrawCache of the rendering
+ The amount the liquid rendered is offset by
+ Whether or not the liquid is in the background
+
+
+
+ Allows you to draw things in front of the liquid at the given coordinates. This can also be used to do things such as rendering glowmasks.
+ This hook is not called if returns false.
+ This method is only called in "Color" and "White" lighting modes. Use for the other Lighting modes post drawing
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+ The LiquidDrawCache of the rendering
+ The amount the liquid rendered is offset by
+ Whether or not the liquid is in the background
+
+
+
+ Allows you to make stuff happen whenever the liquid at the given coordinates is drawn. For example, creating bubble dusts or changing the color the liquid is drawn in.
+ This hook is seperate from Liquid Rendering, Only use this for things such as spawning particles.
+ Return false to stop Lava from spawning some of its bubbles. Returns true by default.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+ Various information about the liquid that is being drawn, such as opacity, visual liquid, etc.
+
+
+
+ Allows you to draw things behind the liquid at the given coordinates. Return false to stop the game from drawing the liquid normally. Returns true by default.
+ This method is only called in "Retro" and "Trippy" lighting modes. Use for the other Lighting modes pre drawing
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+
+
+
+
+ Allows you to draw things in front of the liquid at the given coordinates. This can also be used to do things such as rendering glowmasks.
+ This hook is not called if returns false.
+ This method is only called in "Retro" and "Trippy" lighting modes. Use for the other Lighting modes post drawing
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+
+
+
+
+ Allows you to make stuff happen whenever the liquid at the given coordinates is drawn. For example, creating bubble dusts or changing the color the liquid is drawn in.
+ This hook is not called if returns false.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+
+ Various information about the liquid that is being drawn, such as color, opacity, waterfall length, etc.
+ Gets the amount of liquid in a tile for retro rendering
+ Gets the number of quality the game has for retro rendering
+
+
+
+ Allows you to draw things behind the liquid at the given coordinates. Return false to stop the game from drawing the liquid normally. Returns true by default.
+ Only called for liquid slopes. If you want to predraw the liquid itself, see or
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+ Whether or not the slope is rendered behind tiles
+ The rendering position of the slope. Use this rather than x/y as the rendering can be offset sometimes
+ The size of the liquid
+ The color of the liquid. Usually the light color of the liquid
+
+
+
+ Allows you to draw things in front of the liquid at the given coordinates. This can also be used to do things such as rendering glowmasks.
+ This hook is not called if returns false.
+ Only called for liquid slopes. If you want to postdraw the liquid itself, see or
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+ Whether or not the slope is rendered behind tiles
+ The rendering position of the slope. Use this rather than x/y as the rendering can be offset sometimes
+ The size of the liquid
+ The color of the liquid. Usually the light color of the liquid
+
+
+
+ Allows you to determine how much light this liquid emits.
+ It can also let you light up the block in front of this liquid.
+ See for vanilla tile light values to use as a reference.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+ The red component of light, usually a value between 0 and 1
+ The green component of light, usually a value between 0 and 1
+ The blue component of light, usually a value between 0 and 1
+
+
+
+ Allows for disabling lava bubbles in "Retro" and "Trippy" lighting modes. Only calls when lava's PreRetroDraw isnt false. Returns false by default.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+
+
+
+ The ID of the waterfall/liquidfall style the game should use when the liquid is near a half block.
+ Returns null by default.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+
+
+
+ Allows the changing of liquid movement in-game as well as allowing you to do other stuff with liquids during updates such as custom evaporation. Returns true by default.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+
+
+
+
+
+ Allows you to make liquids evaporate in the underworld. Also allows for disabling of water evaporation. Returns null by default.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+
+
+
+
+ Allows you to change how liquids move when loading or creating a world. Returns true by default.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+
+
+
+
+ Used to change what tile the liquid generates upon coming in contact with another liquid. Use the otherLiquid param to check what liquid this liquid is interacting with.
+ This method is called even if a tile isn't generated. It is recommended that modders use a non-frame important tile as the result, otherwise the tile may fail to generate.
+ It is recomended that developers use PreLiquidMerge for handling custom collisions and effects as that method is only called when a tile is requested to generate.
+ This hook is still called, even if PreLiquidMerge is returned false.
+ NOTE: it is encouraged to set a default tile that this liquid results in, otherwise it will default to stone.
+ Returns 1 by default.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+ The liquid ID of the liquid colliding with this one.
+
+
+
+
+ Used to modify the sound thats played when two liquids merge with each other.
+ Called every time liquids collide and only on clients.
+ Is not called if PreLiquidMerge returns false.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+ The liquid ID of the liquid colliding with this one.
+ The sound to be played, set this to a sound if you don't want the default merge sound to play.
+
+
+
+ Used to do do extra effects and special merges when two liquids collide with each other. Use the otherLiquid param to check which liquid is colliding with this liquid.
+ NOTE: this method is called ONLY on servers when in multiplayer. Make sure you send a packet if you want to do extra visual effects. To learn more about handling custom packets, please see .
+ Return false to prevent the normal liquid merging logic.
+ Retruns true by default.
+
+ The x position of the target liquid in tile coordinates
+ NOTE: This may not always mean the x position of THIS liquid, as it may mean the x position of the other liquid.
+ The y position of the target liquid in tile coordinates
+ NOTE: This may not always mean the y position of THIS liquid, as it may mean the y position of the other liquid.
+ The x position of where the tile is sechedualed to generate at in tile coordninates.
+ NOTE: most of the time this x position is the same as liquid's x position, this means that the tile is being generated over the liquid.
+ Useful for when trying to do something else other than generating a tile.
+ The y position of where the tile is sechedualed to generate at in tile coordninates.
+ NOTE: most of the time this y position is the same as liquid's y position, this means that the tile is being generated over the liquid.
+ Useful for when trying to do something else other than generating a tile.
+
+ The Liquid ID of the liquid colliding with this liquid
+
+
+
+
+ Allows the editing of how fast liquids fall, return null for the regular liquid falling to apply.
+ For Modded Liquids, use ModLiquid.FallDelay property to edit how fast your liquid falls. This method can be used to edit other mod liquids falling as well.
+ Returns null by default
+ NOTE: liquids can only have a maximum fall delay of 10 (which is the same as the fall of Honey), this is due to the delay being reset to 10 when in quickfall mode.
+
+
+
+
+
+
+ Allows you to determine which liquids the given liquid type can be considered as when looking for avaliable liquids.
+
+
+
+
+
+
+ Allows the user to specify whether the liquid prevents the placement or blockswap of a tile over this liquid. Usually used by lava to stop players from placing ontop of it.
+ Return true for the liquid to prevent tile placement, return false if the liquid can have tiles placed over it. Return null for the default logic to run.
+ Returns null by default.
+
+ The player instance thats attempting to place a tile over the liquid.
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+
+
+
+
+ Allows you to decide what happens when the player enters and exits this liquid. Vanilla liquids use this to spawn dusts and make a splashing noise when a player enters and leaves.
+ Players now also have a moddedWet array to show which modded liquids are being entered in at a time. Please see array on how to use it.
+ Return true to allow the liquids to call their normal splash code. Returns true by default.
+
+ The player instance thats entering or exiting the liquid.
+
+ Whether the currently the liquid is being entered or exited.
+
+
+
+ Allows you to decide what happens when a NPC enters and exits this liquid. Vanilla liquids use this to spawn dusts and make a splashing noise when a NPC enters and leaves.
+ NPCs now also have a moddedWet array to show which modded liquids are being entered in at a time. Please see array on how to use it.
+ Return true to allow the liquids to call their normal splash code. Returns true by default.
+
+ The NPC instance thats entering or exiting the liquid.
+
+ Whether the currently the liquid is being entered or exited.
+
+
+
+ Allows you to decide what happens when a projectile enters and exits this liquid. Vanilla liquids use this to spawn dusts and make a splashing noise when a projectile enters and leaves.
+ Projectiles now also have a moddedWet array to show which modded liquids are being entered in at a time. Please see array on how to use it.
+ Return true to allow the liquids to call their normal splash code. Returns true by default.
+
+ The projectile instance thats entering or exiting the liquid.
+
+ Whether the currently the liquid is being entered or exited.
+
+
+
+ Allows you to decide what happens when a fishing bobber catches a fish. Water uses this to create extra water bubbles and to make a splash sound.
+ Return false to disable the water splashing fishing bobbers create.
+
+ The projectile instance thats fishing in the liquid.
+
+
+
+
+
+ Allows you to decide what happens when an item enters and exits this liquid. Vanilla liquids use this to spawn dusts and make a splashing noise when an item enters and leaves.
+ Items now also have a moddedWet array to show which modded liquids are being entered in at a time. Please see array on how to use it.
+ Return true to allow the liquids to call their normal splash code. Returns true by default.
+
+ The item instance thats entering or exiting the liquid.
+
+ Whether the currently the liquid is being entered or exited.
+
+
+
+ Allows the user to specify how a liquid interacts with the player (especially player movement).
+ Please see , , or to see how vanilla handles it's liquid collision.
+ Return true for the liquid to use the normal liquid collision code.
+ Returns true by default.
+
+ The player instance thats being effected by the liquid.
+
+ Whether or not the player is falling through the liquid.
+ Whether or not the player ignores platforms when falling.
+
+
+
+
+ Allows the user to specify how a liquid interacts with the player (especially player gravity).
+ Please see , to see how vanilla handles it's liquid gravity.
+
+ The player instance thats being effected by the liquid.
+
+ The current player.gravity being changed.
+ The current player.maxFallSpeed being changed.
+ The current Player.jumpHeight being changed.
+ The current Player.jumpSpeed being changed.
+
+
+
+ Allows the user to specify how a liquid interacts with an item (especially item gravity and movement).
+ Please see , to see how vanilla handles it's liquid collision.
+ This method is also used to modify items detected to be in liquids. Use this to do things such as deleting items touching this liquid.
+
+ The item instance thats being effected by the liquid.
+
+ The velocity of the item when in the liquid.
+ The gravity of the item.
+ The maximum fall speed of the item.
+
+
+
+ Allows the user to specify how a liquid interacts with a npc (especially npc movement).
+ Please see , to see how vanilla handles it's liquid collision.
+ Return true for the liquid to call the method that applies the liquid velocity multiplier.
+ Returns true by default.
+
+ The npc instance thats being effected by the liquid.
+
+ The velocity of the NPC before being modified by the liquid.
+
+
+
+
+ Allows the user to specify how a liquid interacts with an npc (especially npc gravity).
+ Please see , to see how vanilla handles it's liquid collision.
+
+ The npc instance thats being effected by the liquid.
+
+ The gravity of the npc.
+ The maximum fall speed of the npc.
+
+
+
+ Allows the user to specify how a liquid interacts with a projectile (especially projectile movement).
+ Please see , to see how vanilla handles it's liquid collision.
+ Return true for the liquid to use the normal liquid collision code.
+ Returns true by default.
+
+ The projectile instance thats being effected by the liquid.
+
+ The velocity of the item when in the liquid.
+ The position of where the projectile is calculated when colliding with this liquid.
+ The modified width of this projectile.
+ The modified height of this projectile.
+ Whether or not the projectile can fall through.
+
+
+
+
+ Hook for deciding whether a liquid should allow or disallow, when overtop of the Collision.CheckDrowning position, to be considered drowning or not.
+ Not to be confused with CanPlayersDrown, which is a hook called every frame to check if the player is drowning or not. Useful for making items such as a Breething Reed.
+ Return null to execute the normal Collision.CheckDrowning behaviour. Returns null by default.
+
+
+
+
+
+
+ Hook for deciding whether a liquid should emit breath dusts when a player or npc is slowly drowning.
+ ChecksForDrowning must be set to true for this to run.
+ Return null to execute the normal breath behaviour. Returns null by default.
+
+
+
+
+
+
+ Allows you to give conditions for when the game attempts to check to see if the player is drowning.
+ Set isDrowning to either true or false depending on whether the player should or should not be drowning.
+ This is used by items such as the Breething Reed to make the player be submerged deeper underwater.
+ Please see for how vanilla uses the isDrowning boolean flag.
+ ChecksForDrowning must be set to true for this to run. Not to be confused with ChecksForDrowning hook.
+
+ The player instance thats being effected by the liquid.
+
+ The boolean flag for whether or not the player is drowning.
+
+
+
+ The multiper responsable for the poolsize of liquid being fished in.
+ Honey uses this to multiply its pool size by 1.5x, this means that honey only needs a minimum of 50 tiles rather than 75 tiles of liquid.
+
+
+ The multiplier used, for most liquids this will be 1, but for honey it's 1.5.
+
+
+
+ Allows bobbers to ignore the application of the shimmer effect when being wet by shimmer.
+ This allows modders to easily enable fishing in shimmer. Do keep in mind, the fishing loot normally is water.
+
+
+
+
+
+ The opacity liquid slopes render at. Lava uses this to render at 1f opacity, and honey does the following calculation for it's opacity:
+ Math.Max(0.5f * 1.7f, 1f)
+ The game does additional calulations after this hook to get the final opacity. Use this method to edit liquid slope's default opacity to render at.
+ slopeOpacity defaults at 0.5f.
+
+
+ The opacity already given to a liquid. Edit this to change the default liquid slope opacity.
+
+
+
+ Allows you to change the Light Mask Mode for any liquid. The Light Mask Mode is the mask for lighting to determine how light interacts with a liquid.
+ Vanilla has options for Water (slight blue fade) and Honey (dark black) while lava uses the None option.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+ Edit this param to change the Light Mask Mode of the liquid.
+
+
+
+ The multiplier used when the Waves qaulity setting is set to Medium.
+ Honey and Lava set this multiplier to be 0.3x.
+ This setting is to make waves go the same distance no matter the liquid. For some reason vanilla manually applies a multiplier rather than doing seperate math for the wave speed.
+
+
+ The multiplier used, for most liquids this will be 1f, but for honey and lava it's 0.3.
+
+
+
+ Allows manipulation of tiles when grass burns. This allows modders to make grasses burn with a liquid or do other interactions if a liquid is nearby a tile.
+ Only effects tiles in a 9x9 area around a liquid and only executes every few seconds.
+ Can be used to allow modders to make sure their grasses burn when near lava.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+ The x position of the liquid in tile coordinates.
+ The y position of the liquid in tile coordinates.
+
+
+
+ Allows modders to do extra interactions when a liquid is pumped.
+ Works similarly to a Pre hook, executing before any liquids are moved for each pump.
+ Return true for pumps to execute their normal liquid moving logic.
+ Returns true by default.
+
+
+ The x position of the in pump in tile coordinates.
+ The y position of the in pump in tile coordinates.
+ The x position of the out pump in tile coordinates.
+ The y position of the out pump in tile coordinates.
+
+
+
+
+ A hook to modify a liquid's stopwatch MPH multiplier whether that be modder or vanilla liquids.
+ Water has its multiplier set to 0.5, honey 0.25 and shimmer 0.375 as an example of existing values.
+
+
+ The multiplier for the stopwatch MPH.
+
+
+
+ Executed whenever the collision check for players is executed and found true.
+ This is used for adding de/buffs, damaging the player or incrimenting/deincrementing timers or ModPlayer fields.
+ Vanilla liquids use this to add buffs or debuffs such as On Fire!, Honey, or Shimmering.
+
+ The player instance being effected by this liquid.
+
+
+
+
+ Executed whenever the collision check for NPCs is executed and found true.
+ This is used for adding debuffs, damaging the npc or incrimenting/deincrementing timers or GlobalNPC fields.
+ Vanilla liquids use this to damage the NPC and apply On Fire! when touching lava.
+
+ The NPC instance being effected by this liquid.
+
+
+
+
+ Executed whenever the collision check for projectiles is executed and found true.
+ This is used for changing projectile types, killing projectiles, and doing other misc effects.
+ Vanilla liquids use this to transforming flaming arrows into arrows and killing flamethrower flames.
+
+ The Projectile instance being effected by this liquid.
+
+
+
+
+ Allows you to animate a liquid.
+ Returning false will cause the liquid/s to nolonger play an animation.
+ Use frameState to keep track of how long the current frame has been active, and use frame to change the current frame.
+ GameTime has also been provided to check the current seconds that has overlapped ingame.
+ Returns true by default.
+
+
+ The current amount of time that has passed since the game has been opened.
+ The current frame the liquid is on.
+ The current frame counter the liquid is on.
+
+
+
+
+ Allows you to modify the ripple strength and offset when an NPC enters, exists and moves through a liquid.
+ This is executed right before QueueRipple is called in Terraria.GameContent.Shaders.WaterShaderData.DrawWaves.
+
+ The NPC instance moving through the liquid.
+
+ The strength and size of a ripple.
+ The offset of a ripple.
+
+
+
+ Allows you to modify the ripple strength and offset when a player enters, exists and moves through a liquid.
+ This is executed right before QueueRipple is called in Terraria.GameContent.Shaders.WaterShaderData.DrawWaves.
+
+ The player moving through the liquid.
+
+ The strength and size of a ripple.
+ The offset of a ripple.
+
+
+
+ Contains extra hooks for ModTile that are useful for liquid implementatiom.
+
+
+
+
+ Creates a waterfall at the tile position.
+ Useful when creating a tile similar to rain or snow cloud blocks.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+
+
+
+ Allows the rendering of this tile in liquids.
+ Lily pads use this hook to draw themselves to liquids so water ripples/waves effect those tiles.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+
+
+
+ Gets the ModLiquid instance with the given type. If no ModLiquid with the given type exists, returns null.
+
+
+
+
+
+
+
+ Get the id (type) of a ModLiquid by class. Assumes one instance per class.
+
+
+
+
+ This class represents a type of liquid that can be added by a mod. Only one instance of this class will ever exist for each type of liquid that is added. Any hooks that are called will be called by the instance corresponding to the liquid type. This is to prevent the game from using a massive amount of memory storing liquid instances.
+
+
+
+ The Liquid ID of this Modded Liquid
+
+
+ The block texture of this liquid. Used for some slope framing and when liquids are rendered in retro lighting modes.
+
+
+ The slope texture of this liquid. Used for rendering the liquids next to tile slopes.
+
+
+ The default sound that plays when an entity enters and exits this liquid. Overriding any OnSplash hooks/methods will prevent this from being used.
+
+
+ The default dust ID thats used when an entity enters and exists this liquid. Overriding any OnSplash hooks/methods will prevent this from being used.
+
+
+ Liquids can only have a maximum fall delay of 10 (which is the same as the fall of Honey), this is due to the delay being reset to 10 when in quickfall mode.
+
+
+ The vanilla ID of what should replace the instance when a user unloads and subsequently deletes data from your mod in their save file. Defaults to 0.
+
+
+ An array of the IDs of liquids that this tile can be considered as when looking for available liquids.
+
+
+ The check in Collision that checks if a coord will be drowning in water.
+
+
+ Whether or not, when drowning, a player or npc will emit dusts from their mouth.
+
+
+ The multiplier used to change how many tiles are needed to fish in a pool of liquid. Honey uses a 1.5x multiplier for its pool size.
+
+
+ The multiplier used only when Waves quality setting is set to Medium. Honey and Lava use this to set the modifier to 0.3x.
+
+
+ The opacity that this liquid slope renders at. Lava and Honey use this to look thicker. Defaults to 0.5f.
+
+
+ The multiplier thats used to specify how slow (or fast) the player moves while in this liquid.
+
+
+ The multiplier used for stopwatches to know how to offset the MPH reading.
+
+
+ The default value that ModLiquidNPC.moddedLiquidMovementSpeed sets to before ModNPC.SetDefaults
+
+
+ The multiplier thats used to specify how slow (or fast) projectiles move while in this liquid.
+
+
+ Uses lava based collision check for when applying this liquid's wet boolean.
+ This means collision is more sensitive, and the wet is active even when touching the smallest amount of this liquid.
+
+
+ Whether or not this liquid removes the On Fire! debuffs when entering.
+
+
+ The multiplier repsonsible for multiplying how much opacity each step in this liquid's fall should be drawn at.
+
Only effects slopes when underground (similar to other liquids).
+
+
+
+ Adds an entry to the minimap for this liquid with the given color and display name. This should be called in SetDefaults.
+
+
+
+
+
+
Overload specific: This overload has an additional parameter. This function will be used to dynamically adjust the hover text. The parameters for the function are the default display name, x-coordinate, and y-coordinate.
+
+
+
+
+ Legacy helper method for creating a localization sub-key MapEntry
+
+
+
+
+
+ Allows you to modify the properties after initial loading has completed.
+
This is where you would set the properties of this liquid. Many properties are stored as arrays throughout Terraria's code.
+
For example:
+
+ - WATERFALL_LENGTH = 10
+ - DefaultOpacity = 0.6f;
+ - VisualViscosity = 0;
+
+
+
+
+
+ Allows you to choose which minimap entry the liquid at the given coordinates will use. 0 is the first entry added by AddMapEntry, 1 is the second entry, etc. Returns 0 by default.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+
+
+ Allows you to draw things behind the liquid at the given coordinates. Return false to stop the game from drawing the liquid normally. Returns true by default.
+ This method is only called in "Color" and "White" lighting modes. Use for the other Lighting modes pre drawing
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+ The LiquidDrawCache of the rendering
+ The amount the liquid rendered is offset by
+ Whether or not the liquid is in the background
+
+
+
+ Allows you to draw things in front of the liquid at the given coordinates. This can also be used to do things such as rendering glowmasks.
+ This hook is not called if returns false.
+ This method is only called in "Color" and "White" lighting modes. Use for the other Lighting modes post drawing
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+ The LiquidDrawCache of the rendering
+ The amount the liquid rendered is offset by
+ Whether or not the liquid is in the background
+
+
+
+ Allows you to make stuff happen whenever the liquid at the given coordinates is drawn. For example, creating bubble dusts or changing the color the liquid is drawn in.
+ This hook is seperate from Liquid Rendering, Only use this for things such as spawning particles.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+ Various information about the liquid that is being drawn, such as opacity, visual liquid, etc.
+
+
+
+ Allows you to draw things behind the liquid at the given coordinates. Return false to stop the game from drawing the liquid normally. Returns true by default.
+ This method is only called in "Retro" and "Trippy" lighting modes. Use for the other Lighting modes pre drawing
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+
+
+
+ Allows you to draw things in front of the liquid at the given coordinates. This can also be used to do things such as rendering glowmasks.
+ This hook is not called if returns false.
+ This method is only called in "Retro" and "Trippy" lighting modes. Use for the other Lighting modes post drawing
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+
+
+
+ Allows you to make stuff happen whenever the liquid at the given coordinates is drawn. For example, creating bubble dusts or changing the color the liquid is drawn in.
+ This hook is not called if returns false.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+ Various information about the liquid that is being drawn, such as color, opacity, waterfall length, etc.
+ Gets the amount of liquid in a tile for retro rendering
+ Gets the number of quality the game has for retro rendering
+
+
+
+ Allows you to draw things behind the liquid at the given coordinates. Return false to stop the game from drawing the liquid normally. Returns true by default.
+ Only called for liquid slopes. If you want to predraw the liquid itself, see or
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+ Whether or not the slope is rendered behind tiles
+ The rendering position of the slope. Use this rather than x/y as the rendering can be offset sometimes
+ The size of the liquid
+ The color of the liquid. Usually the light color of the liquid
+
+
+
+ Allows you to draw things in front of the liquid at the given coordinates. This can also be used to do things such as rendering glowmasks.
+ This hook is not called if returns false.
+ Only called for liquid slopes. If you want to postdraw the liquid itself, see or
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+ Whether or not the slope is rendered behind tiles
+ The rendering position of the slope. Use this rather than x/y as the rendering can be offset sometimes
+ The size of the liquid
+ The color of the liquid. Usually the light color of the liquid
+
+
+
+ Allows you to determine how much light this liquid emits.
+ It can also let you light up the block in front of this liquid.
+ See for vanilla tile light values to use as a reference.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+ The red component of light, usually a value between 0 and 1
+ The green component of light, usually a value between 0 and 1
+ The blue component of light, usually a value between 0 and 1
+
+
+
+ Modifies the LightMaskMode used for this liquid.
+ Due to limitations in the lighting engine, tile coordinates and editing of vanilla lightmasks are unavaliable.
+ NOTE: set LiquidLightMaskMode to None for this hook/method to be called. Otherwise this liquid will use the other mask mode instead.
+
+ The current LightMap index. Water uses this to randomise its colors slightly.
+ The red component of light, usually a value between 0 and 1
+ The green component of light, usually a value between 0 and 1
+ The blue component of light, usually a value between 0 and 1
+
+
+
+ Allows you to change the Light Mask Mode for this liquid. The Light Mask Mode is the mask for lighting to determine how light interacts with this liquid.
+ Vanilla has options for Water (slight blue fade) and Honey (dark black) while lava uses the None option.
+ Defaults to LightMaskMode.None.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+
+
+ The ID of the waterfall/liquidfall style the game should use when this liquid is near a half block
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+
+
+ Allows the changing of liquid movement in-game as well as allowing you to do other stuff with liquids during updates such as custom evaporation. Returns true by default.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+
+
+
+
+ Allows you to make your liquid evaporate like water when in the underworld. Returns false by default.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+
+
+
+ Allows you to change how your liquid moves when loading or creating a world. Returns true by default.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+
+
+
+ Used to change what tile the liquid generates upon coming in contact with another liquid. Use the otherLiquid param to check what liquid this liquid is interacting with.
+ This method is called even if a tile isn't generated. It is recommended that modders use a non-frame important tile as the result, otherwise the tile may fail to generate.
+ It is recomended that developers use PreLiquidMerge for handling custom collisions and effects as that method is only called when a tile is requested to generate.
+ This hook is still called, even if PreLiquidMerge is returned false.
+ NOTE: it is encouraged to set a default tile that this liquid results in, otherwise it will default to stone.
+ Returns 1 by default.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+ The liquid ID of the liquid colliding with this one.
+
+
+
+
+ Used to modify the sound thats played when two liquids merge with each other.
+ Called every time liquids collide and only on clients.
+ Is not called if PreLiquidMerge returns false.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+ The liquid ID of the liquid colliding with this one.
+ The sound to be played, set this to a sound if you don't want the default merge sound to play.
+
+
+
+ Used to do do extra effects and special merges when two liquids collide with each other. Use the otherLiquid param to check which liquid is colliding with this liquid.
+ NOTE: this method is called ONLY on servers when in multiplayer. Make sure you send a packet if you want to do extra visual effects. To learn more about handling custom packets, please see .
+ Return false to prevent the normal liquid merging logic.
+ Retruns true by default.
+
+ The x position of the target liquid in tile coordinates
+ NOTE: This may not always mean the x position of THIS liquid, as it may mean the x position of the other liquid.
+ The y position of the target liquid in tile coordinates
+ NOTE: This may not always mean the y position of THIS liquid, as it may mean the y position of the other liquid.
+ The x position of where the tile is sechedualed to generate at in tile coordninates.
+ NOTE: most of the time this x position is the same as liquid's x position, this means that the tile is being generated over the liquid.
+ Useful for when trying to do something else other than generating a tile.
+ The y position of where the tile is sechedualed to generate at in tile coordninates.
+ NOTE: most of the time this y position is the same as liquid's y position, this means that the tile is being generated over the liquid.
+ Useful for when trying to do something else other than generating a tile.
+ The Liquid ID of the liquid colliding with this liquid
+
+
+
+
+ Allows the user to specify whether the liquid prevents the placement or blockswap of a tile over this liquid. Usually used by lava to stop players from placing ontop of it.
+ Return true for the liquid to prevent tile placement, return false if the liquid can have tiles placed over it.
+ Returns false by default.
+
+ The player instance thats attempting to place a tile over the liquid.
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+
+
+
+
+ Allows you to decide what happens when the player enters and exits this liquid. Vanilla liquids use this to spawn dusts and make a splashing noise when a player enters and leaves.
+ Players now also have a moddedWet array to show which modded liquids are being entered in at a time. Please see array on how to use it.
+ Return false for the liquid to not execute the default modded liquid splash code.
+ Returns true by default.
+
+ The player instance thats entering or exiting the liquid.
+ Whether the currently the liquid is being entered or exited.
+
+
+
+
+ Allows you to decide what happens when a NPC enters and exits this liquid. Vanilla liquids use this to spawn dusts and make a splashing noise when a NPC enters and leaves.
+ NPCs now also have a moddedWet array to show which modded liquids are being entered in at a time. Please see array on how to use it.
+ Return false for the liquid to not execute the default modded liquid splash code.
+ Returns true by default.
+
+ The NPC instance thats entering or exiting the liquid.
+ Whether the currently the liquid is being entered or exited.
+
+
+
+
+ Allows you to decide what happens when a projectile enters and exits this liquid. Vanilla liquids use this to spawn dusts and make a splashing noise when a projectile enters and leaves.
+ Projectiles now also have a moddedWet array to show which modded liquids are being entered in at a time. Please see array on how to use it.
+ Return false for the liquid to not execute the default modded liquid splash code.
+ Returns true by default.
+
+ The projectile instance thats entering or exiting the liquid.
+ Whether the currently the liquid is being entered or exited.
+
+
+
+
+ Allows you to decide what happens when an item enters and exits this liquid. Vanilla liquids use this to spawn dusts and make a splashing noise when an item enters and leaves.
+ Items now also have a moddedWet array to show which modded liquids are being entered in at a time. Please see array on how to use it.
+ Return false for the liquid to not execute the default modded liquid splash code.
+ Returns true by default.
+
+ The item instance thats entering or exiting the liquid.
+ Whether the currently the liquid is being entered or exited.
+
+
+
+
+ Allows you to decide what happens when a fishing bobber catches a fish. Water uses this to create extra water bubbles and to make a splash sound. ///
+ The projectile instance thats fishing in the liquid.
+
+
+
+
+ Allows the user to specify how the liquid interacts with the player (especially player movement).
+ Please see , , or to see how vanilla handles it's liquid collision.
+ Return true for the liquid to use the normal liquid collision code.
+ Returns true by default.
+
+ The player instance thats being effected by the liquid.
+ Whether or not the player is falling through the liquid.
+ Whether or not the player ignores platforms when falling.
+
+
+
+
+ Allows the user to specify how the liquid interacts with the player (especially player gravity).
+ Please see , to see how vanilla handles it's liquid gravity.
+
+ The player instance thats being effected by the liquid.
+ The current player.gravity being changed.
+ The current player.maxFallSpeed being changed.
+ The current Player.jumpHeight being changed.
+ The current Player.jumpSpeed being changed.
+
+
+
+ Allows the user to specify how the liquid interacts with an item (especially item gravity and movement).
+ Please see , to see how vanilla handles it's liquid collision.
+ This method is also used to modify items detected to be in liquids. Use this to do things such as deleting items touching this liquid.
+
+ The item instance thats being effected by the liquid.
+ The velocity of the item when in the liquid.
+ The gravity of the item.
+ The maximum fall speed of the item.
+
+
+
+ Allows the user to specify how the liquid interacts with an npc (especially npc movement).
+ Please see , to see how vanilla handles it's liquid collision.
+ Return true for the liquid to call the method that applies the liquid velocity multiplier.
+ Returns true by default.
+
+ The npc instance thats being effected by the liquid.
+ The velocity of the NPC before being modified by the liquid.
+
+
+
+
+ Allows the user to specify how the liquid interacts with an npc (especially npc gravity).
+ Please see , to see how vanilla handles it's liquid gravity.
+
+ The npc instance thats being effected by the liquid.
+ The gravity of the npc.
+ The maximum fall speed of the npc.
+
+
+
+ Allows the user to specify how the liquid interacts with a projectile (especially projectile movement).
+ Please see , to see how vanilla handles it's liquid collision.
+ Return true for the liquid to use the normal liquid collision code.
+ Returns true by default.
+
+ The projectile instance thats being effected by the liquid.
+ The velocity of the item when in the liquid.
+ The position of where the projectile is calculated when colliding with this liquid.
+ The modified width of this projectile.
+ The modified height of this projectile.
+ Whether or not the projectile can fall through.
+
+
+
+
+ Allows you to give conditions for when the game attempts to check to see if the player is drowning.
+ Set isDrowning to either true or false depending on whether the player should or should not be drowning.
+ This is used by items such as the Breething Reed to make the player be submerged deeper underwater.
+ Please see for how vanilla uses the isDrowning boolean flag.
+ ChecksForDrowning must be set to true for this to run. Not to be confused with ChecksForDrowning.
+
+ The player instance thats being effected by the liquid.
+ The boolean flag for whether or not the player is drowning.
+
+
+
+ Allows manipulation of tiles when grass burns. This allows modders to make grasses burn with their liquid or do other interactions if a liquid is nearby a tile.
+ Only effects tiles in a 9x9 area around a liquid and only executes every few seconds.
+
+ The x position in tile coordinates.
+ The y position in tile coordinates.
+ The x position of the liquid in tile coordinates.
+ The y position of the liquid in tile coordinates.
+
+
+
+ Allows modders to do extra interactions when their liquid is pumped.
+ Works similarly to a Pre hook, executing before any liquids are moved for each pump.
+ Return true for pumps to execute their normal liquid moving logic.
+ Returns true by default.
+
+ The x position of the in pump in tile coordinates.
+ The y position of the in pump in tile coordinates.
+ The x position of the out pump in tile coordinates.
+ The y position of the out pump in tile coordinates.
+
+
+
+
+ Executed whenever the collision check for players is executed and found true.
+ This is used for adding de/buffs, damaging the player or incrimenting/deincrementing timers or ModPlayer fields.
+ Vanilla liquids use this to add buffs or debuffs such as On Fire!, Honey, or Shimmering.
+
+ The player instance being effected by this liquid.
+
+
+
+ Executed whenever the collision check for NPCs is executed and found true.
+ This is used for adding debuffs, damaging the npc or incrimenting/deincrementing timers or GlobalNPC fields.
+ Vanilla liquids use this to damage the NPC and apply On Fire! when touching lava.
+
+ The NPC instance being effected by this liquid.
+
+
+
+ Executed whenever the collision check for projectiles is executed and found true.
+ This is used for changing projectile types, killing projectiles, and doing other misc effects.
+ Vanilla liquids use this to transforming flaming arrows into arrows and killing flamethrower flames.
+
+ The Projectile instance being effected by this liquid.
+
+
+
+ Allows you to animate your liquid.
+ Overriding this method will prevent normal vanilla liquid animations from playing, allowing you to animate without interference.
+ Use frameState to keep track of how long the current frame has been active, and use frame to change the current frame.
+ GameTime has also been provided to check the current seconds that has overlapped ingame.
+
+ The current amount of time that has passed since the game has been opened.
+ The current frame the liquid is on.
+ The current frame counter the liquid is on.
+
+
+
+ Allows you to modify the ripple strength and offset when an NPC enters, exists and moves through this liquid.
+ This is executed right before QueueRipple is called in Terraria.GameContent.Shaders.WaterShaderData.DrawWaves.
+
+ The NPC instance moving through the liquid.
+ The strength and size of a ripple.
+ The offset of a ripple.
+
+
+
+ Allows you to modify the ripple strength and offset when a player enters, exists and moves through this liquid.
+ This is executed right before QueueRipple is called in Terraria.GameContent.Shaders.WaterShaderData.DrawWaves.
+
+ The player moving through the liquid.
+ The strength and size of a ripple.
+ The offset of a ripple.
+
+
+
+ The current frame of the waterfall
+
+
+
+
+ The background frame of the waterfall (used for custom rain waterfalls)
+
+
+
+
+ The frame counter of the waterfall
+
+
+
+
+ Allows you to draw things behind the waterfall at the given coordinates. Return false to stop the game from drawing the waterfall normally. Returns true by default.
+
+ The current waterfall data.
+ The x position in tile coordinates.
+ The Y position in tile coordinates.
+
+
+
+
+
+ Allows you to draw things in front of the waterfall at the given coordinates. This can also be used to do things such as rendering glowmasks.
+
+ The current waterfall data, this is used inside of the waterfalls WaterfallData array.
+ The x position in tile coordinates.
+ The Y position in tile coordinates.
+
+
+
+
+
+ Allows you to animate your waterfall.
+ Overriding this method will make your waterfall nolonger animate normally.
+ Use frame to specify which frame the waterfall is using currently.
+ Use frameBackground to specify which background frame the waterfall is using. (This normally goes unused, but is very useful for modders looking into drawing their own waterfalls manually).
+ Rain clouds use this to specify the framing of the rain behind the main rain waterfall.
+ Use frameCounter to specify the duration between frames.
+ Please see ModLiquidExampleMod.Content.Waterfalls.BloodClotLiquidFall.AnimateWaterfall or ModLiquidExampleMod.Content.Waterfalls.HoneyRain.AnimateWaterfall.
+
+ Waterfalls use this to know what frame to use when drawing.
+ Unused normally, can be used by modders for extra framing.
+ Used to specify a certain amount of time between waterfall frames.
+
+
+
+ Edits the opacity of the waterfall. For example: Waterfalls have an opacity of 60% (0.6f) which allows you to see some stuff behind them, while Lavafalls have an opacity of 100% (1f) which prevents you from seeing anything behind.
+ Returns null be default.
+
+ The x position in tile coordinates.
+ The Y position in tile coordinates.
+ The current waterfall water style alpha
+ The maximum length of the waterfall
+
+ Tile at the waterfall position
+
+
+
+
+ Allows you to prevent the waterfall/liquidfall from making any water sounds when on screen. This is useful for waterfalls/liquidfalls that arent made of water. Returns true by default.
+
+
+
+
+
+ Modded liquids start at the index of 0 as vanilla liquids are recorded in their own seperate fields.
+ Use (id - LiquidID.Count) to get the correct modded liquid ID wet type
+
+
+
+
+ Modded liquids start at the index of 0 as vanilla liquids are recorded in their own seperate fields.
+ Use (id - LiquidID.Count) to get the correct modded liquid ID movement speed
+
+
+
+
+ The X position of the Tile
+
+
+
+
+
+
+ The Y position of the Tile
+
+
+
+
+
+
+ Gets the Position of the tile, the same values that would be inputted in Main.tile to get this Tile
+
+
+ The outputted X value, if you want the X by itself use Tile.X
+ The outputted Y value, if you want the Y by itself use Tile.Y
+
+
+
+ Adds a required crafting liquid with the given liquid type to this recipe. Ex: recipe.AddLiquid(LiquidID.Lava)
+
+
+ The liquid identifier.
+ No liquid has ID " + liquidID
+
+
+
+ Adds a required crafting liquid to this recipe with the given liquid name from the given mod. If the mod parameter is null, then it will automatically use a liquid from the mod creating this recipe.
+
+
+ The mod.
+ Name of the liquid.
+ The liquid " + liquidName + " does not exist in mod " + mod.Name + ". If you are trying to use a vanilla tile, try using Recipe.AddLiquid(liquidID).
+
+
+
+ Adds a required crafting liquid to this recipe of the given type of liquid.
+
+
+ The liquid.
+
+
+
+ Adds a required crafting liquid to this recipe of the given type of liquid.
+
+
+
+
diff --git a/Sources/Everglow.Core/Utilities/MathUtils.Geometry.cs b/Sources/Everglow.Core/Utilities/MathUtils.Geometry.cs
index 07b565dc3..d706a6de9 100644
--- a/Sources/Everglow.Core/Utilities/MathUtils.Geometry.cs
+++ b/Sources/Everglow.Core/Utilities/MathUtils.Geometry.cs
@@ -1,3 +1,5 @@
+using Terraria;
+
namespace Everglow.Commons.Utilities;
public static partial class MathUtils
@@ -32,6 +34,38 @@ public static float ToRotationSafe(this Vector2 vector, float defaultValue = def
}
}
+ ///
+ /// 判定2D 圆形与 AABB 是å¦ç›¸äº¤ï¼ˆè¾¹ç•Œç®—相交)
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static bool IntersectsCircleAABB(Vector2 circleCenter, float radius, Vector2 aabbMin, Vector2 aabbMax)
+ {
+ float closestX = Math.Clamp(circleCenter.X, aabbMin.X, aabbMax.X);
+ float closestY = Math.Clamp(circleCenter.Y, aabbMin.Y, aabbMax.Y);
+
+ float dx = circleCenter.X - closestX;
+ float dy = circleCenter.Y - closestY;
+
+ return (dx * dx + dy * dy) <= (radius * radius);
+ }
+
+ ///
+ /// 判定2D 圆形与 AABB 是å¦ç›¸äº¤ï¼ˆè¾¹ç•Œç®—相交)
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static bool IntersectsCircleAABB(Vector2 circleCenter, float radius, Rectangle hitBox)
+ {
+ return IntersectsCircleAABB(circleCenter, radius, hitBox.TopLeft(), hitBox.BottomRight());
+ }
+
///
/// 2D 多边形与 AABB 是å¦ç›¸äº¤
///
@@ -177,6 +211,23 @@ public static bool IsPointInPolygon(List polygon, Vector2 point)
return isInside;
}
+ // Distance from point pos to line defined by points a and b
+ public static float PointToLineDistance(Vector2 a, Vector2 b, Vector2 pos)
+ {
+ float dx = b.X - a.X;
+ float dy = b.Y - a.Y;
+
+ float numerator = MathF.Abs(dy * pos.X - dx * pos.Y + b.X * a.Y - b.Y * a.X);
+ float denominator = MathF.Sqrt(dx * dx + dy * dy);
+
+ if (denominator < float.Epsilon)
+ {
+ return (pos - a).Length(); // a and b are same point
+ }
+
+ return numerator / denominator;
+ }
+
///
/// 判æ–点是å¦åœ¨çº¿æ®µä¸Š
///
@@ -303,6 +354,48 @@ public static bool DoLineSegmentsIntersectByAlgebra(Vector2 p1, Vector2 p2, Vect
return r >= 0 && r <= 1 && s >= 0 && s <= 1;
}
+ ///
+ /// 获å–2D多边形包围盒(AABB)
+ ///
+ ///
+ ///
+ public static Rectangle GetPolygonAABBBound_Rectangle(List polygon)
+ {
+ if (polygon == null || polygon.Count < 3)
+ {
+ return Rectangle.emptyRectangle;
+ }
+
+ Vector4 v4 = GetPolygonAABBBound_Vector4(polygon);
+ return new Rectangle((int)v4.X, (int)v4.Y, (int)(v4.Z - v4.X), (int)(v4.W - v4.Y));
+ }
+
+ ///
+ /// 获å–2D多边形包围盒(AABB)
+ ///
+ ///
+ /// (minX, minY, maxX, maxY) 的 Vector4 结构
+ public static Vector4 GetPolygonAABBBound_Vector4(List polygon)
+ {
+ if (polygon == null || polygon.Count < 3)
+ {
+ return Vector4.zero;
+ }
+
+ float minX = float.MaxValue;
+ float minY = float.MaxValue;
+ float maxX = float.MinValue;
+ float maxY = float.MinValue;
+ foreach (Vector2 p in polygon)
+ {
+ minX = MathF.Min(minX, p.X);
+ minY = MathF.Min(minY, p.Y);
+ maxX = MathF.Max(maxX, p.X);
+ maxY = MathF.Max(maxY, p.Y);
+ }
+ return new Vector4(minX, minY, maxX, maxY);
+ }
+
///
/// æ ¡éªŒå¤šè¾¹å½¢è¾¹æ˜¯å¦ç›¸äº¤ï¼ˆç›¸é‚»è¾¹é™¤å¤–,é¿å…自相交多边形)(未完æˆ)
///
diff --git a/Sources/Everglow.Core/VFX/VFXBatch.cs b/Sources/Everglow.Core/VFX/VFXBatch.cs
index bcabd9eb2..a7e3e4db0 100644
--- a/Sources/Everglow.Core/VFX/VFXBatch.cs
+++ b/Sources/Everglow.Core/VFX/VFXBatch.cs
@@ -12,7 +12,7 @@ public class VFXBatch : IDisposable
private const int MAX_INDICES = MAX_VERTICES * 3;
//numbers Copy from SpriteBatch
- private const int MAX_VERTICES = 8192;
+ private const int MAX_VERTICES = 1048576;
private List buffers = new();
diff --git a/Sources/Everglow.Function/DeveloperContent/Items/TileDataReader.cs b/Sources/Everglow.Function/DeveloperContent/Items/TileDataReader.cs
index 4a2371977..9fbc66bf9 100644
--- a/Sources/Everglow.Function/DeveloperContent/Items/TileDataReader.cs
+++ b/Sources/Everglow.Function/DeveloperContent/Items/TileDataReader.cs
@@ -3,6 +3,8 @@
using Everglow.Commons.Vertex;
using Everglow.Commons.VFX;
using Everglow.Commons.VFX.Pipelines;
+using Terraria;
+using Terraria.ObjectData;
namespace Everglow.Commons.DeveloperContent.Items;
@@ -54,6 +56,7 @@ public class TileDataReaderSystem : Visual
public Point FixPoint;
public static List OwnerPlayerWhoAmI = new List();
public List ContinueTiles = new List();
+ public List SurfaceTiles = new List();
public List CheckLiquidTiles = new List();
public Point OldTilePos = new Point(0, 0);
public bool EverLasting = false;
@@ -110,7 +113,7 @@ public override void Draw()
OwnerPlayerWhoAmI.Remove(player.whoAmI);
return;
}
- Tile tile = Main.tile[i, j];
+ Tile tile = TileUtils.SafeGetTile(i, j);
int colorType = ItemRarityID.White;
Color drawColor = Color.White;
if (!tile.HasTile)
@@ -119,20 +122,31 @@ public override void Draw()
drawColor = Color.Gray;
}
DrawBlockBound(i, j, drawColor);
- if (ContinueTiles.Count < MaxContinueCount)
+ if (tile.HasTile)
{
- var drawContinueColor = new Color(0.12f, 0.24f, 0.4f, 0);
- foreach (Point point in ContinueTiles)
+ if (ContinueTiles.Count < MaxContinueCount)
+ {
+ var drawContinueColor = new Color(0.12f, 0.24f, 0.4f, 0);
+ foreach (var check_tile in ContinueTiles)
+ {
+ DrawBlockBound(check_tile.X, check_tile.Y, drawContinueColor);
+ }
+ }
+ if (SurfaceTiles.Count < MaxContinueCount)
{
- DrawBlockBound(point.X, point.Y, drawContinueColor);
+ var drawSurfaceTilesColor = new Color(0.8f, 0.03f, 0.06f, 0);
+ foreach (var check_tile in SurfaceTiles)
+ {
+ DrawBlockBound(check_tile.X, check_tile.Y, drawSurfaceTilesColor);
+ }
}
}
if (CheckLiquidTiles.Count < MaxContinueCount)
{
var drawContinueColor = new Color(0.0f, 0.0f, 0.6f, 0);
- foreach (Point point in CheckLiquidTiles)
+ foreach (var check_tile in CheckLiquidTiles)
{
- DrawBlockBound(point.X, point.Y, drawContinueColor);
+ DrawBlockBound(check_tile.X, check_tile.Y, drawContinueColor);
}
}
string datas = GetDatas(i, j);
@@ -146,6 +160,7 @@ public string GetDatas(int i, int j)
string datas = "\nCoordinate: [" + i + ", " + j + "]";
datas += "\nHasTile: " + tile.HasTile;
datas += "\nType :" + tile.TileType;
+ //datas += "\nPaint :" + tile.BlockColorAndCoating().Invisible;
if (tile.HasTile)
{
datas += " " + TileID.Search.GetName(tile.TileType);
@@ -154,10 +169,31 @@ public string GetDatas(int i, int j)
{
datas += "\nContinue Tiles : " + ContinueTiles.Count;
}
+ if (SurfaceTiles.Count < MaxContinueCount)
+ {
+ datas += "\nSurface Tiles : " + SurfaceTiles.Count;
+ }
+ int multiStyle = TileObjectData.GetTileStyle(tile);
+ if (multiStyle >= 0)
+ {
+ datas += "\nMultiTile Style: " + multiStyle;
+ }
}
if (!tile.HasTile)
{
- datas += "\nCan Fill Liquid Blocks: " + CheckLiquidTiles.Count;
+ if (CheckLiquidTiles.Count <= 900)
+ {
+ datas += "\nCan Fill Liquid Blocks: " + CheckLiquidTiles.Count;
+ }
+ }
+ //float waterLine;
+ //Collision.GetWaterLine(i, j, out waterLine);
+ //datas += "\n" + waterLine;
+
+ if (tile.WallType > WallID.None)
+ {
+ datas += "\nWallType :" + tile.WallType;
+ datas += " " + WallID.Search.GetName(tile.WallType);
}
// datas += "\nSlope: " + tile.Slope;
@@ -171,105 +207,16 @@ public string GetDatas(int i, int j)
///
public void UpdateContinueTiles(int i, int j)
{
- ContinueTiles = new List();
- CheckLiquidTiles = new List();
- BFSContinueTile(i, j);
- BFSFillLiquid(i, j);
- }
-
- private static readonly (int, int)[] directions =
- {
- (0, 1),
- (1, 0),
- (0, -1),
- (-1, 0),
- };
-
- private static readonly (int, int)[] directionsLiquid =
- {
- (1, 0),
- (0, 1),
- (-1, 0),
- };
-
- public void BFSContinueTile(int i, int j)
- {
- BFSContinueTile(new Point(i, j));
- }
-
- public void BFSContinueTile(Point checkPoint)
- {
- var queueChecked = new Queue();
-
- // å°†èµ·å§‹ç‚¹åŠ å…¥é˜Ÿåˆ—
- queueChecked.Enqueue(checkPoint);
- var visited = new List();
-
- while (queueChecked.Count > 0)
+ Tile tile = TileUtils.SafeGetTile(i, j);
+ if (tile.HasTile)
{
- var tilePos = queueChecked.Dequeue();
-
- foreach (var (dx, dy) in directions)
- {
- int checkX = tilePos.X + dx;
- int checkY = tilePos.Y + dy;
- var point = new Point(checkX, checkY);
- Tile tile = TileUtils.SafeGetTile(checkX, checkY);
-
- // 检查边界和障ç¢ç‰©
- if (checkX >= 20 && checkX < Main.maxTilesX - 20 && checkY >= 20 && checkY < Main.maxTilesY - 20 &&
- tile.HasTile && !visited.Contains(point))
- {
- queueChecked.Enqueue(point);
- visited.Add(point);
- }
- }
- if (queueChecked.Count > MaxContinueCount || visited.Count > MaxContinueCount)
- {
- break;
- }
+ SurfaceTiles = TileUtils.BFSSurface(new Point(i, j), 625);
+ ContinueTiles = TileUtils.BFSContinueTile(new Point(i, j), false, 625);
}
- ContinueTiles = visited;
- }
-
- public void BFSFillLiquid(int i, int j)
- {
- BFSFillLiquid(new Point(i, j));
- }
-
- public void BFSFillLiquid(Point checkPoint)
- {
- var queueChecked = new Queue();
-
- // å°†èµ·å§‹ç‚¹åŠ å…¥é˜Ÿåˆ—
- queueChecked.Enqueue(checkPoint);
- var visited = new List();
-
- while (queueChecked.Count > 0)
+ else
{
- var tilePos = queueChecked.Dequeue();
-
- foreach (var (dx, dy) in directionsLiquid)
- {
- int checkX = tilePos.X + dx;
- int checkY = tilePos.Y + dy;
- var point = new Point(checkX, checkY);
- Tile tile = TileUtils.SafeGetTile(checkX, checkY);
-
- // 检查边界和障ç¢ç‰©
- if (checkX >= 20 && checkX < Main.maxTilesX - 20 && checkY >= 20 && checkY < Main.maxTilesY - 20 &&
- !Collision.IsWorldPointSolid(point.ToWorldCoordinates()) && !visited.Contains(point))
- {
- queueChecked.Enqueue(point);
- visited.Add(point);
- }
- }
- if (queueChecked.Count > MaxContinueCount || visited.Count > MaxContinueCount)
- {
- break;
- }
+ CheckLiquidTiles = TileUtils.BFSGetCanFillLiquidTiles(i, j);
}
- CheckLiquidTiles = visited;
}
public void DrawBlockBound(int i, int j, Color color)
diff --git a/Sources/Everglow.Function/DeveloperContent/Items/TileFliper.cs b/Sources/Everglow.Function/DeveloperContent/Items/TileFliper.cs
new file mode 100644
index 000000000..441a46b5c
--- /dev/null
+++ b/Sources/Everglow.Function/DeveloperContent/Items/TileFliper.cs
@@ -0,0 +1,44 @@
+namespace Everglow.Commons.DeveloperContent.Items;
+
+public class TileFliper : ModItem
+{
+ public override string LocalizationCategory => Utilities.LocalizationUtils.Categories.Tools;
+
+ public bool EnableFlipSystem = false;
+
+ public override void SetDefaults()
+ {
+ Item.DamageType = DamageClass.Magic;
+ Item.damage = 0;
+ Item.width = 34;
+ Item.height = 34;
+ Item.useTime = 2;
+ Item.useAnimation = 2;
+ Item.useStyle = ItemUseStyleID.Swing;
+ Item.noMelee = true;
+ Item.value = 0;
+ Item.rare = ItemRarityID.White;
+ Item.UseSound = SoundID.Item44;
+ Item.noUseGraphic = true;
+ }
+
+ public override void HoldItem(Player player)
+ {
+ // if(Main.mouseLeft && Main.mouseLeftRelease && !EnableFlipSystem)
+ // {
+ // EnableFlipSystem = true;
+ // }
+ if (!EnableFlipSystem)
+ {
+ EnableFlipSystem = true;
+ TileFliperSystemVFX tileFliperSystemVFX = new TileFliperSystemVFX()
+ {
+ Owner = player,
+ Active = true,
+ Visible = true,
+ };
+ Ins.VFXManager.Add(tileFliperSystemVFX);
+ }
+ base.HoldItem(player);
+ }
+}
diff --git a/Sources/Everglow.Function/DeveloperContent/Items/TileFliper.png b/Sources/Everglow.Function/DeveloperContent/Items/TileFliper.png
new file mode 100644
index 000000000..8a24d353f
Binary files /dev/null and b/Sources/Everglow.Function/DeveloperContent/Items/TileFliper.png differ
diff --git a/Sources/Everglow.Function/DeveloperContent/Items/TileFliperSystemVFX.cs b/Sources/Everglow.Function/DeveloperContent/Items/TileFliperSystemVFX.cs
new file mode 100644
index 000000000..c2f15909f
--- /dev/null
+++ b/Sources/Everglow.Function/DeveloperContent/Items/TileFliperSystemVFX.cs
@@ -0,0 +1,177 @@
+using Everglow.Commons.Enums;
+using Everglow.Commons.VFX;
+using Everglow.Commons.VFX.Pipelines;
+
+namespace Everglow.Commons.DeveloperContent.Items;
+
+[Pipeline(typeof(WCSPipeline))]
+public class TileFliperSystemVFX : Visual
+{
+ public Point FixPoint;
+
+ public Point ControlPoint;
+
+ public Player Owner;
+
+ public Item TileFliperItem = null;
+
+ public Rectangle FlipArea()
+ {
+ int minX = Math.Min(FixPoint.X, ControlPoint.X);
+ int maxX = Math.Max(FixPoint.X, ControlPoint.X);
+ int minY = Math.Min(FixPoint.Y, ControlPoint.Y);
+ int maxY = Math.Max(FixPoint.Y, ControlPoint.Y);
+ return new Rectangle(minX, minY, maxX - minX + 1, maxY - minY + 1);
+ }
+
+ public override CodeLayer DrawLayer => CodeLayer.PostDrawTiles;
+
+ public override void Update()
+ {
+ if (Owner.HeldItem.type == ModContent.ItemType())
+ {
+ if (TileFliperItem is null)
+ {
+ TileFliperItem = Owner.HeldItem;
+ }
+ TileFliper tf = TileFliperItem.ModItem as TileFliper;
+ if (tf != null)
+ {
+ tf.EnableFlipSystem = true;
+ }
+ }
+ else
+ {
+ Kill();
+ return;
+ }
+
+ if (Main.mouseLeft && Main.mouseLeftRelease)
+ {
+ FixPoint = Main.MouseWorld.ToTileCoordinates();
+ }
+ if (Main.mouseLeft)
+ {
+ ControlPoint = Main.MouseWorld.ToTileCoordinates();
+ }
+ if (Main.mouseRight && Main.mouseRightRelease)
+ {
+ FlipTheTileMap();
+ }
+ }
+
+ public void FlipTheTileMap()
+ {
+ Rectangle flip = FlipArea();
+ for (int i = 0; i < flip.Width / 2; i++)
+ {
+ for (int j = 0; j < flip.Height; j++)
+ {
+ var tile0 = Main.tile[i + flip.X, j + flip.Y];
+ var tile1 = Main.tile[flip.X + flip.Width - i - 1, j + flip.Y];
+ (tile0.TileType, tile1.TileType) = (tile1.TileType, tile0.TileType);
+ (tile0.HasTile, tile1.HasTile) = (tile1.HasTile, tile0.HasTile);
+ (tile0.WallType, tile1.WallType) = (tile1.WallType, tile0.WallType);
+ (tile0.Slope, tile1.Slope) = (tile1.Slope, tile0.Slope);
+ ReverseSlope(i + flip.X, j + flip.Y);
+ ReverseSlope(flip.X + flip.Width - i - 1, j + flip.Y);
+ (tile0.LiquidType, tile1.LiquidType) = (tile1.LiquidType, tile0.LiquidType);
+ (tile0.LiquidAmount, tile1.LiquidAmount) = (tile1.LiquidAmount, tile0.LiquidAmount);
+ (tile0.TileColor, tile1.TileColor) = (tile1.TileColor, tile0.TileColor);
+ (tile0.WallColor, tile1.WallColor) = (tile1.WallColor, tile0.WallColor);
+ (tile0.IsHalfBlock, tile1.IsHalfBlock) = (tile1.IsHalfBlock, tile0.IsHalfBlock);
+ (tile0.TileFrameX, tile1.TileFrameX) = (tile1.TileFrameX, tile0.TileFrameX);
+ (tile0.TileFrameY, tile1.TileFrameY) = (tile1.TileFrameY, tile0.TileFrameY);
+ (tile0.HasActuator, tile1.HasActuator) = (tile1.HasActuator, tile0.HasActuator);
+ (tile0.IsActuated, tile1.IsActuated) = (tile1.IsActuated, tile0.IsActuated);
+ }
+ }
+ for (int i = 0; i < flip.Width; i++)
+ {
+ for (int j = 0; j < flip.Height; j++)
+ {
+ WorldGen.SquareTileFrame(i + flip.X, j + flip.Y);
+ WorldGen.SquareWallFrame(i + flip.X, j + flip.Y);
+ }
+ }
+ }
+
+ public void ReverseSlope(int i, int j)
+ {
+ Tile tile = Main.tile[i, j];
+ if (tile.Slope == SlopeType.SlopeDownLeft)
+ {
+ tile.Slope = SlopeType.SlopeDownRight;
+ return;
+ }
+ if (tile.Slope == SlopeType.SlopeUpLeft)
+ {
+ tile.Slope = SlopeType.SlopeUpRight;
+ return;
+ }
+ if (tile.Slope == SlopeType.SlopeDownRight)
+ {
+ tile.Slope = SlopeType.SlopeDownLeft;
+ return;
+ }
+ if (tile.Slope == SlopeType.SlopeUpRight)
+ {
+ tile.Slope = SlopeType.SlopeUpLeft;
+ return;
+ }
+ }
+
+ public override void Kill()
+ {
+ if (TileFliperItem != null)
+ {
+ TileFliper tf = TileFliperItem.ModItem as TileFliper;
+ if (tf != null)
+ {
+ tf.EnableFlipSystem = false;
+ }
+ }
+ base.Kill();
+ }
+
+ public override void Draw()
+ {
+ Rectangle drawTileArea = FlipArea();
+ var startPoint = new Point(drawTileArea.X, drawTileArea.Y);
+ Texture2D tex = ModAsset.TileBlock4x4.Value;
+ Color drawColor = new Color(0.4f, 0.2f, 1f, 0.3f);
+ for (int i = 0; i < drawTileArea.Width; i++)
+ {
+ for (int j = 0; j < drawTileArea.Height; j++)
+ {
+ Vector2 drawPos = (startPoint + new Point(i, j)).ToWorldCoordinates();
+ Rectangle drawFrame = new Rectangle(16, 16, 16, 16);
+ if (i == 0)
+ {
+ drawFrame.X = 0;
+ }
+ if (j == 0)
+ {
+ drawFrame.Y = 0;
+ }
+ if (i == drawTileArea.Width - 1)
+ {
+ drawFrame.X = 32;
+ }
+ if (j == drawTileArea.Height - 1)
+ {
+ drawFrame.Y = 32;
+ }
+ if (i == drawTileArea.Width - 1 && i == 0)
+ {
+ drawFrame.X = 48;
+ }
+ if (j == drawTileArea.Height - 1 && j == 0)
+ {
+ drawFrame.Y = 48;
+ }
+ Ins.Batch.Draw(tex, drawPos, drawFrame, drawColor, 0, new Vector2(8), 1f, SpriteEffects.None);
+ }
+ }
+ }
+}
diff --git a/Sources/Everglow.Function/DeveloperContent/Items/TileToolBox.cs b/Sources/Everglow.Function/DeveloperContent/Items/TileToolBox.cs
new file mode 100644
index 000000000..673f8546e
--- /dev/null
+++ b/Sources/Everglow.Function/DeveloperContent/Items/TileToolBox.cs
@@ -0,0 +1,36 @@
+using Everglow.Commons.DeveloperContent.VFXs;
+
+namespace Everglow.Commons.DeveloperContent.Items;
+
+///
+/// Create line-connected points in world, help developers to visualize polygon.
+///
+public class TileToolBox : ModItem
+{
+ public TileToolBoxInterface Visual { get; private set; } = null;
+
+ public override void SetDefaults()
+ {
+ Item.width = 16;
+ Item.height = 16;
+ Item.value = 0;
+ Item.rare = ItemRarityID.White;
+ }
+
+ public override void HoldItem(Player player)
+ {
+ if (Main.mouseLeft && Main.mouseLeftRelease)
+ {
+ if (Visual is not null && Visual.Active)
+ {
+ return;
+ }
+ var helper = new TileToolBoxInterface()
+ {
+ Owner = player,
+ };
+ Ins.VFXManager.Add(helper);
+ Visual = helper;
+ }
+ }
+}
diff --git a/Sources/Everglow.Function/DeveloperContent/Items/TileToolBox.png b/Sources/Everglow.Function/DeveloperContent/Items/TileToolBox.png
new file mode 100644
index 000000000..f4ee6ba4c
Binary files /dev/null and b/Sources/Everglow.Function/DeveloperContent/Items/TileToolBox.png differ
diff --git a/Sources/Everglow.Function/DeveloperContent/Items/WorldAnchor.cs b/Sources/Everglow.Function/DeveloperContent/Items/WorldAnchor.cs
new file mode 100644
index 000000000..c535fb51a
--- /dev/null
+++ b/Sources/Everglow.Function/DeveloperContent/Items/WorldAnchor.cs
@@ -0,0 +1,44 @@
+using Everglow.Commons.Utilities;
+using Terraria;
+
+namespace Everglow.Commons.DeveloperContent.Items;
+
+///
+/// Visulalize the data of mouse-covered-tile.
+///
+public class WorldAnchor : ModItem
+{
+ public bool EnableResidentEffect = false;
+
+ public override void SetDefaults()
+ {
+ Item.width = 16;
+ Item.height = 16;
+ Item.value = 0;
+ Item.rare = ItemRarityID.White;
+ }
+
+ public override void HoldItem(Player player)
+ {
+ int i = Main.MouseWorld.ToTileCoordinates().X;
+ int j = Main.MouseWorld.ToTileCoordinates().Y;
+ if (Main.mapFullscreen)
+ {
+ Vector2 mouseFromCenter = Main.MouseScreen - new Vector2(Main.screenWidth, Main.screenHeight) / 2f;
+ Vector2 mouseMap = Main.mapFullscreenPos + mouseFromCenter / Main.mapFullscreenScale * Main.GameViewMatrix.Zoom;
+ i = (int)mouseMap.X;
+ j = (int)mouseMap.Y;
+ }
+
+ string text = string.Empty;
+ var tile = TileUtils.SafeGetTile(i, j);
+ if (tile.HasTile)
+ {
+ text += "TileType :" + tile.TileType;
+ text += " " + TileID.Search.GetName(tile.TileType);
+ }
+ text += "\n[" + i + ", " + j + "]\n";
+ text += "[" + i / (float)Main.maxTilesX + ", " + j / (float)Main.maxTilesY + "]";
+ Main.instance.MouseText(text);
+ }
+}
diff --git a/Sources/Everglow.Function/DeveloperContent/Items/WorldAnchor.png b/Sources/Everglow.Function/DeveloperContent/Items/WorldAnchor.png
new file mode 100644
index 000000000..f633ecd23
Binary files /dev/null and b/Sources/Everglow.Function/DeveloperContent/Items/WorldAnchor.png differ
diff --git a/Sources/Everglow.Function/DeveloperContent/VFXs/TileToolBoxInterface.cs b/Sources/Everglow.Function/DeveloperContent/VFXs/TileToolBoxInterface.cs
new file mode 100644
index 000000000..12a87b3e3
--- /dev/null
+++ b/Sources/Everglow.Function/DeveloperContent/VFXs/TileToolBoxInterface.cs
@@ -0,0 +1,922 @@
+using Everglow.Commons.DeveloperContent.Items;
+using Everglow.Commons.Enums;
+using Everglow.Commons.TileHelper;
+using Everglow.Commons.Utilities;
+using Everglow.Commons.Vertex;
+using Everglow.Commons.VFX;
+using Everglow.Commons.VFX.Pipelines;
+using Terraria.GameContent;
+using static Everglow.Commons.Utilities.MathUtils;
+using static Everglow.Commons.Utilities.TileUtils;
+using static Everglow.Commons.VFX.CommonDusts.LightDust;
+
+namespace Everglow.Commons.DeveloperContent.VFXs;
+
+[Pipeline(typeof(WCSPipeline))]
+public class TileToolBoxInterface : Visual
+{
+ public const int TotalTool = 12;
+
+ public Player Owner = null;
+ public Vector2 Position;
+ public int CurrentTileType;
+ public int CurrentWallType = 0;
+ public int SelectedTool = -1;
+ public int MouseOverTool = -1;
+ public int Timer;
+ public int PlayerHeldItemTile = -1;
+ public int PlayerHeldItemWall = -1;
+
+ ///
+ /// 0: Tile, 1: Wall
+ ///
+ public int State = 0;
+ public bool Open = true;
+ public bool ShouldDrawMouseTlie = false;
+ public bool ShouldDrawBrushCoveredTlies = false;
+ public bool ShouldDrawSelectedTlies = false;
+ public bool RectangleSelecting = false;
+ public bool Brushing = false;
+ public bool ClickAnyButtonInThisFrame = false;
+ public bool CircleSelecting = false;
+ public Point RectangleSelectStart;
+ public Point RectangleSelectEnd;
+ public Point CircleSelectCenter;
+ public float CircleSelectRadius;
+ public float BrushSize = 16;
+ public string MouseText;
+
+ public enum ToolID
+ {
+ TilePicker,
+ TileColorBoard,
+ PaintBucket,
+ MagicWand,
+ Undo,
+ Redo,
+ RectangleSelect,
+ PolygonSelect,
+ CircleSelect,
+ Unselect,
+ PaintBrush,
+ SwitchTileAndWall,
+ None,
+ History,
+ Smoothe,
+ }
+
+ public class ToolButton
+ {
+ public float Scale;
+ public Vector2 Position;
+ public int Type;
+ }
+
+ public List Tools = [];
+ public List SelectedTiles = [];
+ public List CurrentSelectedTiles = [];
+ public List BrushCoveredTiles = [];
+ public List BrushPaintedTiles = [];
+ public List PolygonSelectPoints = [];
+ public static Stack<(MapIO Mp, string Pt)> UndoMapIOs = [];
+ public static Stack<(MapIO Mp, string Pt)> RedoMapIOs = [];
+
+ public override CodeLayer DrawLayer => CodeLayer.PostDrawDusts;
+
+ public override void Update()
+ {
+ if (Tools.Count <= 0)
+ {
+ Initialization();
+ }
+ UpdateActive();
+ if (ClickAnyButtonInThisFrame && Main.mouseLeftRelease)
+ {
+ ClickAnyButtonInThisFrame = false;
+ }
+
+ if (Main.mouseRight && Main.mouseRightRelease)
+ {
+ UpdateRightClick();
+ }
+ if (Main.mouseLeft && Main.mouseLeftRelease)
+ {
+ UpdateLeftClick();
+ }
+ UpdateTools();
+ }
+
+ ///
+ /// Initialize the tool buttons. This method is called once when the visual is first updated, and it populates the Tools list with the necessary buttons for the interface.
+ ///
+ public void Initialization()
+ {
+ for (int k = 0; k < TotalTool; k++)
+ {
+ Tools.Add(new ToolButton()
+ {
+ Position = Vector2.zeroVector,
+ Scale = 1f,
+ Type = k,
+ });
+ }
+ }
+
+ public void UpdateActive()
+ {
+ if (Owner.HeldItem is not null)
+ {
+ if (State == 0)
+ {
+ if (Owner.HeldItem.createTile != PlayerHeldItemTile && Owner.HeldItem.createTile >= 0)
+ {
+ CurrentTileType = Owner.HeldItem.createTile;
+ }
+ }
+ PlayerHeldItemTile = Owner.HeldItem.createTile;
+ if (State == 1)
+ {
+ if (Owner.HeldItem.createWall != PlayerHeldItemWall && Owner.HeldItem.createWall >= 1)
+ {
+ CurrentWallType = Owner.HeldItem.createWall;
+ }
+ }
+ PlayerHeldItemWall = Owner.HeldItem.createWall;
+ }
+ else
+ {
+ PlayerHeldItemTile = -1;
+ }
+ if (Open)
+ {
+ if (Timer < 60)
+ {
+ Timer += 6;
+ }
+ }
+ else
+ {
+ if (Timer > 0)
+ {
+ Timer -= 6;
+ }
+ else
+ {
+ Active = false;
+ return;
+ }
+ }
+ }
+
+ public void UpdateTools()
+ {
+ for (int t = Tools.Count - 1; t >= 0; t--)
+ {
+ var ui = Tools[t];
+ float value = Timer / 60f;
+ value = MathF.Pow(value, 0.5f);
+ ui.Position = new Vector2(0, value * TotalTool * 6).RotatedBy(ui.Type / (float)Tools.Count * MathHelper.TwoPi - 1 + value);
+ Tools[t] = ui;
+ }
+ ShouldDrawMouseTlie = false;
+ ShouldDrawBrushCoveredTlies = false;
+ ShouldDrawSelectedTlies = false;
+ switch (SelectedTool)
+ {
+ case (int)ToolID.TilePicker:
+ ShouldDrawMouseTlie = true;
+ break;
+ case (int)ToolID.RectangleSelect:
+ ShouldDrawSelectedTlies = true;
+ ShouldDrawMouseTlie = true;
+ if (!ClickAnyButtonInThisFrame)
+ {
+ if (Main.mouseLeft)
+ {
+ if (!RectangleSelecting)
+ {
+ RectangleSelecting = true;
+ RectangleSelectStart = Main.MouseWorld.ToTileCoordinates();
+ }
+ RectangleSelectEnd = Main.MouseWorld.ToTileCoordinates();
+ CurrentSelectedTiles = GetAABBAreaOfTile(RectangleSelectStart, RectangleSelectEnd);
+ }
+ else
+ {
+ RectangleSelecting = false;
+ SelectedTiles.AddRangeDistinct(CurrentSelectedTiles);
+ CurrentSelectedTiles = [];
+ }
+ }
+ break;
+ case (int)ToolID.PolygonSelect:
+ ShouldDrawSelectedTlies = true;
+ ShouldDrawMouseTlie = true;
+ break;
+ case (int)ToolID.CircleSelect:
+ ShouldDrawSelectedTlies = true;
+ ShouldDrawMouseTlie = true;
+ if (!ClickAnyButtonInThisFrame)
+ {
+ if (Main.mouseLeft)
+ {
+ if (!CircleSelecting)
+ {
+ CircleSelecting = true;
+ var point = Main.MouseWorld.ToTileCoordinates();
+ CircleSelectCenter = point;
+ }
+ CircleSelectRadius = (CircleSelectCenter.ToWorldCoordinates() - Main.MouseWorld).Length() / 16f;
+ CurrentSelectedTiles = GetCircleAreaOfTilePos(CircleSelectCenter, CircleSelectRadius);
+ }
+ else
+ {
+ CircleSelecting = false;
+ SelectedTiles.AddRangeDistinct(CurrentSelectedTiles);
+ CurrentSelectedTiles = [];
+ }
+ }
+ break;
+ case (int)ToolID.MagicWand:
+ ShouldDrawSelectedTlies = true;
+ break;
+ case (int)ToolID.PaintBucket:
+ ShouldDrawSelectedTlies = true;
+ break;
+ case (int)ToolID.PaintBrush:
+ ShouldDrawBrushCoveredTlies = true;
+ if (!ClickAnyButtonInThisFrame)
+ {
+ Point brushStart = (Main.MouseWorld - new Vector2(BrushSize)).ToTileCoordinates();
+ Point brushEnd = (Main.MouseWorld + new Vector2(BrushSize)).ToTileCoordinates();
+ BrushCoveredTiles = GetAABBAreaOfTile(brushStart, brushEnd);
+ if (Main.mouseLeft)
+ {
+ Brushing = true;
+
+ // HashSet set = new HashSet(BrushPaintedTiles);
+ // foreach (var pos in BrushCoveredTiles)
+ // {
+ // set.Add(pos);
+ // }
+ // BrushPaintedTiles = set.ToList();
+ BrushPaintedTiles.AddRangeDistinct(BrushCoveredTiles);
+ }
+ if (!Main.mouseLeft && Brushing)
+ {
+ if (BrushPaintedTiles.Count > 0)
+ {
+ SaveStepToUndoable(BrushPaintedTiles);
+ }
+ foreach (var pos in BrushPaintedTiles)
+ {
+ var tile = SafeGetTile(pos);
+ if (State == 0)
+ {
+ ChangeTile(tile, CurrentTileType, 0);
+ }
+ if (State == 1)
+ {
+ ChangeWall(tile, CurrentWallType, 0);
+ }
+ WorldGen.TileFrame(pos.X, pos.Y, true, true);
+ WorldGen.SquareWallFrame(pos.X, pos.Y);
+ }
+ BrushPaintedTiles = [];
+ }
+ }
+ break;
+ }
+ }
+
+ public void UpdateLeftClick()
+ {
+ var mouseTile = SafeGetTile(Main.MouseWorld.ToTileCoordinates());
+ if (MouseOverTool >= 0)
+ {
+ if (SelectedTool == (int)ToolID.PolygonSelect)
+ {
+ SelectedTiles.AddRangeDistinct(CurrentSelectedTiles);
+ CurrentSelectedTiles = [];
+ }
+ if (MouseOverTool == SelectedTool)
+ {
+ SelectedTool = -1;
+ ClickAnyButtonInThisFrame = true;
+ }
+ else
+ {
+ switch (MouseOverTool)
+ {
+ case -1:
+ SelectedTool = -1;
+ break;
+ case (int)ToolID.Undo:
+ SelectedTool = -1;
+ if (UndoMapIOs.Count > 0)
+ {
+ var mapIOandStream_undo = UndoMapIOs.Pop();
+ SaveStepToRedoable(mapIOandStream_undo.Mp);
+ ReadMapIO(mapIOandStream_undo);
+ File.Delete(mapIOandStream_undo.Pt);
+ }
+ break;
+ case (int)ToolID.Redo:
+ SelectedTool = -1;
+ if (RedoMapIOs.Count > 0)
+ {
+ var mapIOandStream_redo = RedoMapIOs.Pop();
+ SaveStepToUndoable(mapIOandStream_redo.Mp);
+ ReadMapIO(mapIOandStream_redo);
+ File.Delete(mapIOandStream_redo.Pt);
+ }
+ break;
+ case (int)ToolID.Unselect:
+ SelectedTiles = [];
+ CurrentSelectedTiles = [];
+ PolygonSelectPoints = [];
+ break;
+ case (int)ToolID.SwitchTileAndWall:
+ State += 1;
+ State %= 2;
+ break;
+ default:
+ SelectedTool = MouseOverTool;
+ break;
+ }
+ if (MouseOverTool != -1)
+ {
+ ClickAnyButtonInThisFrame = true;
+ }
+ PolygonSelectPoints = [];
+ }
+ }
+ else
+ {
+ RectangleSelecting = false;
+ CircleSelecting = false;
+ switch (SelectedTool)
+ {
+ case -1:
+ if (Owner.HeldItem.type == ModContent.ItemType())
+ {
+ Position = Main.MouseWorld;
+ Timer = 0;
+ }
+ break;
+ case (int)ToolID.PaintBucket:
+ SaveStepToUndoable(SelectedTiles);
+ foreach (var pos in SelectedTiles)
+ {
+ if (State == 0)
+ {
+ ChangeTile(SafeGetTile(pos), CurrentTileType, (int)TileChangeState.Forceful);
+ }
+ else if (State == 1)
+ {
+ ChangeWall(SafeGetTile(pos), CurrentWallType, (int)TileChangeState.Forceful);
+ }
+ WorldGen.TileFrame(pos.X, pos.Y, true, true);
+ WorldGen.SquareWallFrame(pos.X, pos.Y);
+ }
+ break;
+ case (int)ToolID.TilePicker:
+ if (State == 0)
+ {
+ if (mouseTile.HasTile)
+ {
+ CurrentTileType = mouseTile.TileType;
+ }
+ else
+ {
+ CurrentTileType = -1;
+ }
+ }
+ else if (State == 1)
+ {
+ CurrentWallType = mouseTile.WallType;
+ }
+ break;
+ case (int)ToolID.RectangleSelect:
+ break;
+ case (int)ToolID.PolygonSelect:
+ if (!ClickAnyButtonInThisFrame)
+ {
+ var point = Main.MouseWorld.ToTileCoordinates();
+ if (!PolygonSelectPoints.Contains(point))
+ {
+ PolygonSelectPoints.Add(point);
+ }
+ else
+ {
+ PolygonSelectPoints.Remove(point);
+ }
+ if (PolygonSelectPoints.Count >= 3)
+ {
+ CurrentSelectedTiles = GetPolygonAreaOfTilePos(PolygonSelectPoints);
+ }
+ else
+ {
+ CurrentSelectedTiles.Clear();
+ }
+ }
+ break;
+ case (int)ToolID.MagicWand:
+ if (!ClickAnyButtonInThisFrame)
+ {
+ var point = Main.MouseWorld.ToTileCoordinates();
+ if (State == 0)
+ {
+ if (mouseTile.HasTile)
+ {
+ SelectedTiles.AddRangeDistinct(BFSContinueTile(point, false, 2048, [mouseTile.TileType]));
+ }
+ else
+ {
+ SelectedTiles.AddRangeDistinct(BFSContinueEmpty(point, false, 2048));
+ }
+ }
+ if (State == 1)
+ {
+ SelectedTiles.AddRangeDistinct(BFSContinueWall(point, 2048, [mouseTile.WallType]));
+ }
+ }
+ break;
+ case (int)ToolID.CircleSelect:
+ break;
+ }
+ }
+ }
+
+ public void UpdateRightClick()
+ {
+ switch (SelectedTool)
+ {
+ case -1:
+ Open = false;
+ break;
+ default:
+ if (SelectedTool == (int)ToolID.PolygonSelect)
+ {
+ SelectedTiles.AddRangeDistinct(CurrentSelectedTiles);
+ CurrentSelectedTiles = [];
+ }
+ SelectedTool = -1;
+ break;
+ }
+ }
+
+ public override void Draw()
+ {
+ MouseText = " ";
+ if (Main.mapFullscreen)
+ {
+ return;
+ }
+ MouseOverTool = -1;
+ foreach (var ui in Tools)
+ {
+ DrawToolUI(ui);
+ }
+ if (MouseOverTool != -1)
+ {
+ MouseText += Enum.GetName(typeof(ToolID), MouseOverTool);
+ }
+ if (SelectedTool == (int)ToolID.TilePicker && MouseOverTool == -1)
+ {
+ int type = -1;
+ var checkTile = SafeGetTile(Main.MouseWorld.ToTileCoordinates());
+ if (State == 0)
+ {
+ if (checkTile.HasTile)
+ {
+ type = checkTile.TileType;
+ }
+ }
+ else if (State == 1)
+ {
+ type = checkTile.WallType;
+ }
+ if (MouseText.Length > 2)
+ {
+ MouseText += "\n";
+ }
+ MouseText += "[c/00FFFF:";
+ if (State == 0)
+ {
+ AddTileData(type);
+ }
+ else if (State == 1)
+ {
+ AddWallData(type);
+ }
+ MouseText += "]";
+ }
+ if (MouseOverTool == (int)ToolID.TileColorBoard)
+ {
+ MouseText += "\n";
+ if (State == 0)
+ {
+ AddTileData(CurrentTileType);
+ }
+ else if (State == 1)
+ {
+ AddWallData(CurrentWallType);
+ }
+ }
+ if (SelectedTool != -1)
+ {
+ Texture2D tex = ModAsset.TileToolBoxUI.Value;
+ Rectangle frame = ToolFrame(SelectedTool);
+ Ins.Batch.Draw(tex, Main.MouseWorld + new Vector2(16), frame, Color.White, 0, frame.Size() / 2f, 0.75f, SpriteEffects.None);
+ if (SelectedTool == (int)ToolID.PolygonSelect)
+ {
+ DrawSelectPolygon();
+ }
+ if (SelectedTool == (int)ToolID.CircleSelect && CircleSelecting)
+ {
+ Texture2D point = ModAsset.LightPoint2.Value;
+ Ins.Batch.Draw(point, CircleSelectCenter.ToWorldCoordinates(), null, new Color(0.4f, 0.4f, 1f, 0f), 0, point.Size() * 0.5f, 1f, SpriteEffects.None);
+ }
+ if (MouseOverTool == -1)
+ {
+ if (MouseText.Length > 2)
+ {
+ MouseText += "\n";
+ }
+ MouseText += "[c/666666:Right Click to Cancel the Tool.]";
+ }
+ }
+ if (ShouldDrawMouseTlie)
+ {
+ DrawTile(Main.MouseWorld.ToTileCoordinates(), new Color(1f, 0.75f, 0.15f, 0.4f));
+ }
+ if (ShouldDrawBrushCoveredTlies)
+ {
+ var drawColor = new Color(1f, 0.0f, 0.2f, 0.7f);
+ if (State == 1)
+ {
+ drawColor = new Color(0f, 0.6f, 0.1f, 0.7f);
+ }
+ DrawListOfTiles(BrushPaintedTiles, drawColor);
+ DrawListOfTiles(BrushCoveredTiles, new Color(0.7f, 0.4f, 0.4f, 0.4f));
+ }
+ if (ShouldDrawSelectedTlies)
+ {
+ DrawListOfTiles(CurrentSelectedTiles, new Color(0.7f, 0.4f, 0.4f, 0.4f));
+ DrawListOfTiles(SelectedTiles, new Color(0.7f, 0.4f, 0.4f, 0.4f) * 0.5f);
+ }
+ Main.instance.MouseText(MouseText, ItemRarityID.White);
+ if (State == 0 && CurrentTileType >= 0)
+ {
+ Main.instance.LoadTiles(CurrentTileType);
+ Texture2D tileTex = TextureAssets.Tile[CurrentTileType].Value;
+ var frame = new Rectangle(162, 54, 16, 16);
+ Ins.Batch.Draw(tileTex, Position, frame, Color.White, 0, frame.Size() * 0.5f, 1f, SpriteEffects.None);
+ }
+ if (State == 1 && CurrentWallType >= 1)
+ {
+ Main.instance.LoadWall(CurrentWallType);
+ Texture2D wallTex = TextureAssets.Wall[CurrentWallType].Value;
+ var frame = new Rectangle(324, 108, 32, 32);
+ Ins.Batch.Draw(wallTex, Position, frame, Color.White, 0, frame.Size() * 0.5f, 1f, SpriteEffects.None);
+ }
+ }
+
+ public void DrawSelectPolygon()
+ {
+ Texture2D point = ModAsset.LightPoint2.Value;
+ for (int i = 0; i < PolygonSelectPoints.Count; i++)
+ {
+ float drawScale = 0.75f;
+ var drawColor = new Color(0.4f, 0.4f, 1f, 0f) * 0.5f;
+ if (Main.MouseWorld.ToTileCoordinates() == PolygonSelectPoints[i])
+ {
+ drawColor = new Color(1f, 0.7f, 0f, 0f);
+ drawScale = 1f;
+ }
+ Ins.Batch.Draw(point, PolygonSelectPoints[i].ToWorldCoordinates(), null, drawColor, 0, point.Size() * 0.5f, drawScale, SpriteEffects.None);
+ if (PolygonSelectPoints.Count >= 2)
+ {
+ Vector2 next;
+ if (i < PolygonSelectPoints.Count - 1)
+ {
+ next = PolygonSelectPoints[i + 1].ToWorldCoordinates();
+ }
+ else
+ {
+ next = PolygonSelectPoints[0].ToWorldCoordinates();
+ }
+ DrawLine(PolygonSelectPoints[i].ToWorldCoordinates(), next);
+ }
+ }
+ }
+
+ public void DrawLine(Vector2 pos0, Vector2 pos1)
+ {
+ var drawColor = new Color(0, 0.2f, 0.4f, 0);
+ Texture2D tex = ModAsset.White.Value;
+ List bars = new List();
+ Vector2 dir = (pos0 - pos1).RotatedBy(MathHelper.PiOver2).NormalizeSafe();
+ bars.Add(pos0 + dir, drawColor, new Vector3(0, 0, 0));
+ bars.Add(pos0 - dir, drawColor, new Vector3(0, 0, 0));
+ bars.Add(pos1 + dir, drawColor, new Vector3(0, 0, 0));
+ bars.Add(pos1 - dir, drawColor, new Vector3(0, 0, 0));
+ Ins.Batch.Draw(tex, bars, PrimitiveType.TriangleStrip);
+ }
+
+ public void DrawTile(Point pos, Color color)
+ {
+ Texture2D tile = ModAsset.TileBlock.Value;
+ Ins.Batch.Draw(tile, pos.ToWorldCoordinates(), null, color, 0, tile.Size() / 2f, 1f, SpriteEffects.None);
+ }
+
+ public void DrawListOfTiles(List tiles, Color drawColor)
+ {
+ Texture2D tex = ModAsset.TileBlock4x4.Value;
+ foreach (var pos in tiles)
+ {
+ if (!VFXManager.InScreen(pos.ToWorldCoordinates(), 32))
+ {
+ continue;
+ }
+ Rectangle drawFrame = new Rectangle(16, 16, 16, 16);
+ if (!tiles.Contains(pos + new Point(-1, 0)))
+ {
+ drawFrame.X = 0;
+ }
+ if (!tiles.Contains(pos + new Point(0, -1)))
+ {
+ drawFrame.Y = 0;
+ }
+ if (!tiles.Contains(pos + new Point(1, 0)))
+ {
+ drawFrame.X = 32;
+ }
+ if (!tiles.Contains(pos + new Point(0, 1)))
+ {
+ drawFrame.Y = 32;
+ }
+ if (!tiles.Contains(pos + new Point(-1, 0)) && !tiles.Contains(pos + new Point(1, 0)))
+ {
+ drawFrame.X = 48;
+ }
+ if (!tiles.Contains(pos + new Point(0, -1)) && !tiles.Contains(pos + new Point(0, 1)))
+ {
+ drawFrame.Y = 48;
+ }
+ Ins.Batch.Draw(tex, pos.ToWorldCoordinates(), drawFrame, drawColor, 0, drawFrame.Size() / 2f, 1f, SpriteEffects.None);
+ }
+ }
+
+ public void DrawToolUI(ToolButton tool)
+ {
+ Texture2D tex = ModAsset.TileToolBoxUI.Value;
+ Texture2D panel = ModAsset.Wires_0.Value;
+ Rectangle frame = ToolFrame(tool.Type);
+ Vector2 pos = Position + tool.Position;
+ tool.Scale = 1f;
+ if ((Main.MouseWorld - pos).Length() < 20)
+ {
+ MouseOverTool = tool.Type;
+ panel = ModAsset.Wires_1.Value;
+ tool.Scale = 1.2f;
+ }
+
+ Ins.Batch.Draw(panel, pos, null, Color.White, 0, panel.Size() / 2f, tool.Scale, SpriteEffects.None);
+ Ins.Batch.Draw(tex, pos, frame, Color.White, 0, frame.Size() / 2f, tool.Scale, SpriteEffects.None);
+ }
+
+ public void AddTileData(int type)
+ {
+ string datas = "Clear Tile(-1)";
+ if (type >= 0)
+ {
+ datas = TileID.Search.GetName(type) + "(" + type + ")";
+ }
+ MouseText += datas;
+ }
+
+ public void AddWallData(int type)
+ {
+ string datas = "Clear Wall(-1)";
+ if (type >= 0)
+ {
+ datas = WallID.Search.GetName(type) + "(" + type + ")";
+ }
+ MouseText += datas;
+ }
+
+ public Rectangle ToolFrame(int id)
+ {
+ Rectangle frame = new Rectangle(0, 0, 32, 32);
+ switch (id)
+ {
+ case (int)ToolID.TilePicker:
+ frame = new Rectangle(2, 6, 26, 26);
+ break;
+ case (int)ToolID.TileColorBoard:
+ frame = new Rectangle(40, 22, 28, 20);
+ if (State == 0)
+ {
+ if (CurrentTileType >= 0)
+ {
+ frame = new Rectangle(40, 0, 28, 20);
+ }
+ }
+ else if (State == 1)
+ {
+ if (CurrentWallType >= 1)
+ {
+ frame = new Rectangle(40, 0, 28, 20);
+ }
+ }
+ break;
+ case (int)ToolID.PaintBucket:
+ frame = new Rectangle(76, 10, 22, 20);
+ break;
+ case (int)ToolID.History:
+ frame = new Rectangle(106, 4, 30, 30);
+ break;
+ case (int)ToolID.Undo:
+ frame = new Rectangle(142, 12, 18, 18);
+ if (UndoMapIOs.Count <= 0)
+ {
+ frame.X += 48;
+ }
+ break;
+ case (int)ToolID.Redo:
+ frame = new Rectangle(166, 12, 18, 18);
+ if (RedoMapIOs.Count <= 0)
+ {
+ frame.X += 48;
+ }
+ break;
+ case (int)ToolID.RectangleSelect:
+ frame = new Rectangle(8, 42, 18, 18);
+ break;
+ case (int)ToolID.PolygonSelect:
+ frame = new Rectangle(36, 42, 18, 18);
+ break;
+ case (int)ToolID.CircleSelect:
+ frame = new Rectangle(62, 42, 18, 18);
+ break;
+ case (int)ToolID.Unselect:
+ frame = new Rectangle(88, 42, 18, 18);
+ break;
+ case (int)ToolID.PaintBrush:
+ frame = new Rectangle(120, 44, 22, 20);
+ break;
+ case (int)ToolID.None:
+ frame = new Rectangle(12, 68, 16, 22);
+ break;
+ case (int)ToolID.MagicWand:
+ frame = new Rectangle(36, 68, 20, 20);
+ break;
+ case (int)ToolID.Smoothe:
+ frame = new Rectangle(64, 72, 18, 14);
+ break;
+ case (int)ToolID.SwitchTileAndWall:
+ frame = new Rectangle(88, 72, 20, 20);
+ break;
+ }
+ if (State == 1)
+ {
+ frame.Y += 100;
+ }
+ return frame;
+ }
+
+ public Rectangle GetBoundOfTiles(List tiles)
+ {
+ int x = int.MaxValue;
+ int y = int.MaxValue;
+ int x_max = 0;
+ int y_max = 0;
+ foreach (var pos in tiles)
+ {
+ if (pos.X < x)
+ {
+ x = pos.X;
+ }
+ if (pos.Y < y)
+ {
+ y = pos.Y;
+ }
+ if (pos.X > x_max)
+ {
+ x_max = pos.X;
+ }
+ if (pos.Y > y_max)
+ {
+ y_max = pos.Y;
+ }
+ }
+ int width = x_max - x + 1;
+ int height = y_max - y + 1;
+ return new Rectangle(x, y, width, height);
+ }
+
+ public void ReadMapIO((MapIO Mp, string Pt) item)
+ {
+ var mapIO = item.Mp;
+ var path = item.Pt;
+ mapIO.Read(path);
+ var it = mapIO.GetEnumerator();
+ while (it.MoveNext())
+ {
+ WorldGen.SquareTileFrame(it.CurrentCoord.X, it.CurrentCoord.Y);
+ WorldGen.SquareWallFrame(it.CurrentCoord.X, it.CurrentCoord.Y);
+ }
+ }
+
+ public void SaveStepToUndoable(List tiles)
+ {
+ if (tiles.Count <= 0)
+ {
+ return;
+ }
+ Rectangle area = GetBoundOfTiles(tiles);
+ var mapIO = new MapIO(area);
+ string path = Path.Combine(Main.SavePath, "Mods", "ModDatas", "Everglow");
+ path = Path.Combine(path, "TileToolBox");
+ if (!Directory.Exists(path))
+ {
+ Directory.CreateDirectory(path);
+ }
+
+ string writePath = path + "\\Undo" + UndoMapIOs.Count.ToString() + ".mapio";
+ mapIO.Write(writePath);
+ UndoMapIOs.Push((mapIO, writePath));
+ }
+
+ public void SaveStepToRedoable(MapIO mapIO)
+ {
+ string path = Path.Combine(Main.SavePath, "Mods", "ModDatas", "Everglow");
+ path = Path.Combine(path, "TileToolBox");
+ if (!Directory.Exists(path))
+ {
+ Directory.CreateDirectory(path);
+ }
+
+ string writePath = path + "\\Redo" + RedoMapIOs.Count.ToString() + ".mapio";
+ mapIO.Write(writePath);
+ RedoMapIOs.Push((mapIO, writePath));
+ }
+
+ public void SaveStepToUndoable(MapIO mapIO)
+ {
+ string path = Path.Combine(Main.SavePath, "Mods", "ModDatas", "Everglow");
+ path = Path.Combine(path, "TileToolBox");
+ if (!Directory.Exists(path))
+ {
+ Directory.CreateDirectory(path);
+ }
+
+ string writePath = path + "\\Undo" + UndoMapIOs.Count.ToString() + ".mapio";
+ mapIO.Write(writePath);
+ UndoMapIOs.Push((mapIO, writePath));
+ }
+
+ public static void ClearHistory()
+ {
+ string path = Path.Combine(Main.SavePath, "Mods", "ModDatas", "Everglow");
+ path = Path.Combine(path, "TileToolBox");
+ if (!Directory.Exists(path))
+ {
+ return;
+ }
+ DeleteFilesByPattern(path, "*.mapio");
+ UndoMapIOs = [];
+ RedoMapIOs = [];
+ }
+
+ public static void DeleteFilesByPattern(string directoryPath, string searchPattern = "*.*")
+ {
+ if (!Directory.Exists(directoryPath))
+ {
+ Console.WriteLine($" Path does not exist.: {directoryPath}");
+ return;
+ }
+
+ int deletedCount = 0;
+ try
+ {
+ string[] files = Directory.GetFiles(directoryPath, searchPattern);
+
+ foreach (string file in files)
+ {
+ File.Delete(file);
+ deletedCount++;
+ }
+
+ Console.WriteLine($" {deletedCount} Have been deleted.");
+ return;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($" Fail: {ex.Message}");
+ return;
+ }
+ }
+}
diff --git a/Sources/Everglow.Function/DeveloperContent/VFXs/TileToolBoxSystem.cs b/Sources/Everglow.Function/DeveloperContent/VFXs/TileToolBoxSystem.cs
new file mode 100644
index 000000000..79e724138
--- /dev/null
+++ b/Sources/Everglow.Function/DeveloperContent/VFXs/TileToolBoxSystem.cs
@@ -0,0 +1,26 @@
+using Everglow.Commons.DeveloperContent.Items;
+using Everglow.Commons.Enums;
+using Everglow.Commons.TileHelper;
+using Everglow.Commons.Utilities;
+using Everglow.Commons.Vertex;
+using Everglow.Commons.VFX;
+using Everglow.Commons.VFX.Pipelines;
+using static Everglow.Commons.Utilities.MathUtils;
+using static Everglow.Commons.Utilities.TileUtils;
+
+namespace Everglow.Commons.DeveloperContent.VFXs;
+
+public class TileToolBoxSystem : ModSystem
+{
+ public override void OnWorldLoad()
+ {
+ TileToolBoxInterface.ClearHistory();
+ base.OnWorldLoad();
+ }
+
+ public override void OnWorldUnload()
+ {
+ TileToolBoxInterface.ClearHistory();
+ base.OnWorldUnload();
+ }
+}
diff --git a/Sources/Everglow.Function/DeveloperContent/VFXs/TileToolBoxSystemListExtension.cs b/Sources/Everglow.Function/DeveloperContent/VFXs/TileToolBoxSystemListExtension.cs
new file mode 100644
index 000000000..89198959e
--- /dev/null
+++ b/Sources/Everglow.Function/DeveloperContent/VFXs/TileToolBoxSystemListExtension.cs
@@ -0,0 +1,16 @@
+namespace Everglow.Commons.DeveloperContent.VFXs;
+
+public static class TileToolBoxSystemListExtension
+{
+ public static void AddRangeDistinct(this List list, IEnumerable source)
+ {
+ HashSet temp = new HashSet(list);
+ foreach (var item in source)
+ {
+ temp.Add(item);
+ }
+
+ list.Clear();
+ list.AddRange(temp);
+ }
+}
diff --git a/Sources/Everglow.Function/DeveloperContent/VFXs/TileToolBoxUI.png b/Sources/Everglow.Function/DeveloperContent/VFXs/TileToolBoxUI.png
new file mode 100644
index 000000000..1a69d9fe8
Binary files /dev/null and b/Sources/Everglow.Function/DeveloperContent/VFXs/TileToolBoxUI.png differ
diff --git a/Sources/Everglow.Function/Mechanics/ElementalDebuff/ElementalDebuffInstance.cs b/Sources/Everglow.Function/Mechanics/ElementalDebuff/ElementalDebuffInstance.cs
index 7bc76eb7e..830d67ca4 100644
--- a/Sources/Everglow.Function/Mechanics/ElementalDebuff/ElementalDebuffInstance.cs
+++ b/Sources/Everglow.Function/Mechanics/ElementalDebuff/ElementalDebuffInstance.cs
@@ -190,7 +190,6 @@ public void ApplyDot(NPC npc)
{
return;
}
-
npc.lifeRegen -= Handler.DotDamage;
npc.SetLifeRegenExpectedLossPerSecond(Handler.DotDamage);
}
diff --git a/Sources/Everglow.Function/Textures/CrossStar.png b/Sources/Everglow.Function/Textures/CrossStar.png
new file mode 100644
index 000000000..3ab25c90c
Binary files /dev/null and b/Sources/Everglow.Function/Textures/CrossStar.png differ
diff --git a/Sources/Everglow.Function/Textures/CrossStar_black.png b/Sources/Everglow.Function/Textures/CrossStar_black.png
new file mode 100644
index 000000000..176cab564
Binary files /dev/null and b/Sources/Everglow.Function/Textures/CrossStar_black.png differ
diff --git a/Sources/Everglow.Function/Textures/Noise_WaterFallWave.png b/Sources/Everglow.Function/Textures/Noise_WaterFallWave.png
new file mode 100644
index 000000000..ad5f84825
Binary files /dev/null and b/Sources/Everglow.Function/Textures/Noise_WaterFallWave.png differ
diff --git a/Sources/Everglow.Function/Textures/Noise_flame_2_pure.png b/Sources/Everglow.Function/Textures/Noise_flame_2_pure.png
new file mode 100644
index 000000000..d6ce3fd32
Binary files /dev/null and b/Sources/Everglow.Function/Textures/Noise_flame_2_pure.png differ
diff --git a/Sources/Everglow.Function/Textures/Noise_flame_2_pure_black.png b/Sources/Everglow.Function/Textures/Noise_flame_2_pure_black.png
new file mode 100644
index 000000000..5ffc4f9b8
Binary files /dev/null and b/Sources/Everglow.Function/Textures/Noise_flame_2_pure_black.png differ
diff --git a/Sources/Everglow.Function/Textures/SquareBloom.png b/Sources/Everglow.Function/Textures/SquareBloom.png
new file mode 100644
index 000000000..e404699e5
Binary files /dev/null and b/Sources/Everglow.Function/Textures/SquareBloom.png differ
diff --git a/Sources/Everglow.Function/Textures/SquareBloom_black.png b/Sources/Everglow.Function/Textures/SquareBloom_black.png
new file mode 100644
index 000000000..df8283c36
Binary files /dev/null and b/Sources/Everglow.Function/Textures/SquareBloom_black.png differ
diff --git a/Sources/Everglow.Function/Textures/SquarePiece.png b/Sources/Everglow.Function/Textures/SquarePiece.png
new file mode 100644
index 000000000..668470cfb
Binary files /dev/null and b/Sources/Everglow.Function/Textures/SquarePiece.png differ
diff --git a/Sources/Everglow.Function/Textures/TileBlock4x4.png b/Sources/Everglow.Function/Textures/TileBlock4x4.png
new file mode 100644
index 000000000..5ff38424e
Binary files /dev/null and b/Sources/Everglow.Function/Textures/TileBlock4x4.png differ
diff --git a/Sources/Everglow.Function/Textures/Vanilla_Chat_Back.png b/Sources/Everglow.Function/Textures/Vanilla_Chat_Back.png
new file mode 100644
index 000000000..d9c391e83
Binary files /dev/null and b/Sources/Everglow.Function/Textures/Vanilla_Chat_Back.png differ
diff --git a/Sources/Everglow.Function/Textures/Vanilla_Chat_Back_Highlight.png b/Sources/Everglow.Function/Textures/Vanilla_Chat_Back_Highlight.png
new file mode 100644
index 000000000..e66f8f653
Binary files /dev/null and b/Sources/Everglow.Function/Textures/Vanilla_Chat_Back_Highlight.png differ
diff --git a/Sources/Everglow.Function/Textures/Vanilla_Chat_Back_gray.png b/Sources/Everglow.Function/Textures/Vanilla_Chat_Back_gray.png
new file mode 100644
index 000000000..ca2b68341
Binary files /dev/null and b/Sources/Everglow.Function/Textures/Vanilla_Chat_Back_gray.png differ
diff --git a/Sources/Everglow.Function/TileHelper/AirTile.cs b/Sources/Everglow.Function/TileHelper/AirTile.cs
index d28bb57e6..2976cc94f 100644
--- a/Sources/Everglow.Function/TileHelper/AirTile.cs
+++ b/Sources/Everglow.Function/TileHelper/AirTile.cs
@@ -1,3 +1,4 @@
+
namespace Everglow.Commons.TileHelper;
public class AirTile : ModTile
@@ -6,21 +7,7 @@ public override void SetStaticDefaults()
{
Main.tileSolid[Type] = true;
Main.tileMergeDirt[Type] = true;
- Main.tileBlockLight[Type] = true;
- AddMapEntry(Color.White);
- }
-}
-
-public class AirTileItem : ModItem
-{
- public override string LocalizationCategory => Everglow.Commons.Utilities.LocalizationUtils.Categories.Placeables;
-
- public override void SetDefaults()
- {
- Item.useTime = 5;
- Item.useAnimation = 5;
- Item.createTile = ModContent.TileType();
- Item.useStyle = ItemUseStyleID.Swing;
- Item.autoReuse = true;
+ Main.tileBlockLight[Type] = false;
+ AddMapEntry(Color.Transparent);
}
}
diff --git a/Sources/Everglow.Function/TileHelper/AirTile.png b/Sources/Everglow.Function/TileHelper/AirTile.png
index 8765fb6cf..1397e4f70 100644
Binary files a/Sources/Everglow.Function/TileHelper/AirTile.png and b/Sources/Everglow.Function/TileHelper/AirTile.png differ
diff --git a/Sources/Everglow.Function/TileHelper/AirTileItem.cs b/Sources/Everglow.Function/TileHelper/AirTileItem.cs
new file mode 100644
index 000000000..360c0f5c4
--- /dev/null
+++ b/Sources/Everglow.Function/TileHelper/AirTileItem.cs
@@ -0,0 +1,15 @@
+namespace Everglow.Commons.TileHelper;
+
+public class AirTileItem : ModItem
+{
+ public override string LocalizationCategory => Everglow.Commons.Utilities.LocalizationUtils.Categories.Placeables;
+
+ public override void SetDefaults()
+ {
+ Item.useTime = 5;
+ Item.useAnimation = 5;
+ Item.createTile = ModContent.TileType();
+ Item.useStyle = ItemUseStyleID.Swing;
+ Item.autoReuse = true;
+ }
+}
diff --git a/Sources/Everglow.Function/TileHelper/AirWall.cs b/Sources/Everglow.Function/TileHelper/AirWall.cs
index 43e91efa4..bd978b0a6 100644
--- a/Sources/Everglow.Function/TileHelper/AirWall.cs
+++ b/Sources/Everglow.Function/TileHelper/AirWall.cs
@@ -1,3 +1,4 @@
+
namespace Everglow.Commons.TileHelper;
public class AirWall : ModWall
@@ -6,6 +7,12 @@ public override void SetStaticDefaults()
{
AddMapEntry(Color.White);
}
+
+ public override bool PreDraw(int i, int j, SpriteBatch spriteBatch)
+ {
+ return false;
+ base.PreDraw(i, j, spriteBatch);
+ }
}
public class AirWallItem : ModItem
@@ -16,7 +23,7 @@ public override void SetDefaults()
{
Item.useTime = 5;
Item.useAnimation = 5;
- Item.createTile = ModContent.WallType();
+ Item.createWall = ModContent.WallType();
Item.useStyle = ItemUseStyleID.Swing;
Item.autoReuse = true;
}
diff --git a/Sources/Everglow.Function/TileHelper/AirWall.png b/Sources/Everglow.Function/TileHelper/AirWall.png
index 8765fb6cf..05a13cf9b 100644
Binary files a/Sources/Everglow.Function/TileHelper/AirWall.png and b/Sources/Everglow.Function/TileHelper/AirWall.png differ
diff --git a/Sources/Everglow.Function/TileHelper/CableKnot.png b/Sources/Everglow.Function/TileHelper/CableKnot.png
index 81a362f8c..586e489fd 100644
Binary files a/Sources/Everglow.Function/TileHelper/CableKnot.png and b/Sources/Everglow.Function/TileHelper/CableKnot.png differ
diff --git a/Sources/Everglow.Function/TileHelper/CableTile.cs b/Sources/Everglow.Function/TileHelper/CableTile.cs
index b7ee95721..2cdbe3b52 100644
--- a/Sources/Everglow.Function/TileHelper/CableTile.cs
+++ b/Sources/Everglow.Function/TileHelper/CableTile.cs
@@ -48,6 +48,11 @@ public abstract class CableTile : ModTile, ITileFluentlyDrawn
///
public float Elasticity = 60;
+ ///
+ /// How far should start drawing the rope in an area out of screen .
+ ///
+ public float DrawOffScreenRange = 1200f;
+
public override void SetStaticDefaults()
{
Main.tileFrameImportant[Type] = true;
@@ -467,22 +472,22 @@ public static bool TryGetCableEntityAs(int i, int j, out T entity)
///
/// é¼ æ ‡åˆ’è¿‡ç‚¹ä½
///
- public Dictionary MouseOverPoint = new Dictionary();
+ public Dictionary MouseOverWinchPlayers = new Dictionary();
public override void MouseOver(int i, int j)
{
- if (!MouseOverPoint.ContainsKey(Main.LocalPlayer))
+ if (!MouseOverWinchPlayers.ContainsKey(Main.LocalPlayer))
{
- MouseOverPoint.Add(Main.LocalPlayer, new Point(i, j));
+ MouseOverWinchPlayers.Add(Main.LocalPlayer, new Point(i, j));
if (Main.LocalPlayer.HeldItem.ModItem is CableTileItem)
{
CableTilePlaceHelpingSystem vfx = new CableTilePlaceHelpingSystem { FixPoint = new Point(i, j), Active = true, Visible = true, Style = 0 };
Ins.VFXManager.Add(vfx);
}
}
- else if (MouseOverPoint[Main.LocalPlayer] != new Point(i, j))
+ else if (MouseOverWinchPlayers[Main.LocalPlayer] != new Point(i, j))
{
- MouseOverPoint.Remove(Main.LocalPlayer);
+ MouseOverWinchPlayers.Remove(Main.LocalPlayer);
}
}
@@ -602,9 +607,9 @@ public override void Update()
if (cableTile.HasHoldRope.ContainsKey(Main.LocalPlayer))
{
Active = false;
- if (cableTile.MouseOverPoint.ContainsKey(Main.LocalPlayer))
+ if (cableTile.MouseOverWinchPlayers.ContainsKey(Main.LocalPlayer))
{
- cableTile.MouseOverPoint.Remove(Main.LocalPlayer);
+ cableTile.MouseOverWinchPlayers.Remove(Main.LocalPlayer);
}
return;
}
@@ -613,9 +618,9 @@ public override void Update()
if (x != FixPoint.X || y != FixPoint.Y)
{
Active = false;
- if (cableTile.MouseOverPoint.ContainsKey(Main.LocalPlayer))
+ if (cableTile.MouseOverWinchPlayers.ContainsKey(Main.LocalPlayer))
{
- cableTile.MouseOverPoint.Remove(Main.LocalPlayer);
+ cableTile.MouseOverWinchPlayers.Remove(Main.LocalPlayer);
}
return;
}
diff --git a/Sources/Everglow.Function/TileHelper/CableTile_HangingTile_GlobaDrawing.cs b/Sources/Everglow.Function/TileHelper/CableTile_HangingTile_GlobaDrawing.cs
new file mode 100644
index 000000000..b0926fc0c
--- /dev/null
+++ b/Sources/Everglow.Function/TileHelper/CableTile_HangingTile_GlobaDrawing.cs
@@ -0,0 +1,133 @@
+using System.Reflection;
+using Everglow.Commons.Utilities;
+using Everglow.Commons.VFX;
+using MonoMod.Cil;
+using Terraria.GameContent.Drawing;
+
+namespace Everglow.Commons.TileHelper;
+
+public class CableTile_HangingTile_GlobaDrawing : GlobalTile
+{
+ public override void Load()
+ {
+ Ins.HookManager.AddHook(typeof(TileDrawing).GetMethod(nameof(TileDrawing.Draw), BindingFlags.Public | BindingFlags.Instance), ILHook_TileDrawing_DrawCableTile_HangingTile);
+ }
+
+ private void ILHook_TileDrawing_DrawCableTile_HangingTile(ILContext il)
+ {
+ ILCursor cursor = new ILCursor(il);
+ if (cursor.TryGotoNext(
+ MoveType.After,
+ x => x.MatchStfld(typeof(TileDrawing).GetField("_martianGlow", BindingFlags.NonPublic | BindingFlags.Instance)),
+ x => x.MatchLdarg(0), // åŒ¹é… ldarg.0
+ x => x.MatchLdfld(typeof(TileDrawing).GetField("_currentTileDrawInfo", BindingFlags.NonPublic | BindingFlags.Instance)))) // åŒ¹é… ldfld
+ {
+ cursor.Index += 2;
+ cursor.EmitDelegate(ILHook_SearchCableTile_HangingTilesAndCallPreDraw);
+ }
+ }
+
+ private void ILHook_SearchCableTile_HangingTilesAndCallPreDraw()
+ {
+ Vector2 unscaledPosition = Main.Camera.UnscaledPosition;
+ Vector2 vector = new Vector2(Main.offScreenRange);
+ if (Main.drawToScreen)
+ {
+ vector = Vector2.Zero;
+ }
+ GetScreenDrawArea(unscaledPosition, vector + (Main.Camera.UnscaledPosition - Main.Camera.ScaledPosition), out int firstTileX, out int lastTileX, out int firstTileY, out int lastTileY);
+ foreach (var hangingTile in TileLoader.tiles.OfType())
+ {
+ foreach (var tilePos in hangingTile.RopesOfAllThisTileInTheWorld.Keys)
+ {
+ var worldPos = tilePos.ToWorldCoordinates();
+ if (VFXManager.InScreen(worldPos, hangingTile.DrawOffScreenRange) && (tilePos.X < firstTileX - 2 || tilePos.X >= lastTileX + 2 || tilePos.Y < firstTileY || tilePos.Y >= lastTileY + 4))
+ {
+ int type = Main.tile[tilePos].type;
+ TileLoader.PreDraw(tilePos.X, tilePos.Y, type, Main.spriteBatch);
+ }
+ }
+ }
+ foreach (var cableTile in TileLoader.tiles.OfType())
+ {
+ foreach (var tilePos in cableTile.RopesOfAllThisTileInTheWorld.Keys)
+ {
+ var worldPos = tilePos.ToWorldCoordinates();
+ if (VFXManager.InScreen(worldPos, cableTile.DrawOffScreenRange) && (tilePos.X < firstTileX - 2 || tilePos.X >= lastTileX + 2 || tilePos.Y < firstTileY || tilePos.Y >= lastTileY + 4))
+ {
+ int type = Main.tile[tilePos].type;
+ TileLoader.PreDraw(tilePos.X, tilePos.Y, type, Main.spriteBatch);
+ }
+ }
+ }
+
+ foreach (var offestScreenTile in TileLoader.tiles.OfType())
+ {
+ for (int x = ITileOffsetOverScreenDrawn.SpecialTilePositon.Count - 1; x >= 0; x--)
+ {
+ var tilePos = ITileOffsetOverScreenDrawn.SpecialTilePositon[x];
+ var worldPos = tilePos.ToWorldCoordinates();
+ if (VFXManager.InScreen(worldPos, offestScreenTile.TileOffsetScreenRange()) && (tilePos.X < firstTileX - 2 || tilePos.X >= lastTileX + 2 || tilePos.Y < firstTileY || tilePos.Y >= lastTileY + 4))
+ {
+ var tile = Main.tile[tilePos];
+ if (tile.HasTile && TileLoader.GetTile(tile.type) is ITileOffsetOverScreenDrawn)
+ {
+ int type = tile.type;
+ TileLoader.PreDraw(tilePos.X, tilePos.Y, type, Main.spriteBatch);
+ }
+ else
+ {
+ ITileOffsetOverScreenDrawn.SpecialTilePositon.Remove(tilePos);
+ }
+ }
+ }
+ }
+ }
+
+ private void GetScreenDrawArea(Vector2 screenPosition, Vector2 offSet, out int firstTileX, out int lastTileX, out int firstTileY, out int lastTileY)
+ {
+ firstTileX = (int)((screenPosition.X - offSet.X) / 16f - 1f);
+ lastTileX = (int)((screenPosition.X + Main.screenWidth + offSet.X) / 16f) + 2;
+ firstTileY = (int)((screenPosition.Y - offSet.Y) / 16f - 1f);
+ lastTileY = (int)((screenPosition.Y + Main.screenHeight + offSet.Y) / 16f) + 5;
+ if (firstTileX < 4)
+ {
+ firstTileX = 4;
+ }
+
+ if (lastTileX > Main.maxTilesX - 4)
+ {
+ lastTileX = Main.maxTilesX - 4;
+ }
+
+ if (firstTileY < 4)
+ {
+ firstTileY = 4;
+ }
+
+ if (lastTileY > Main.maxTilesY - 4)
+ {
+ lastTileY = Main.maxTilesY - 4;
+ }
+ }
+
+ public override bool PreDraw(int i, int j, int type, SpriteBatch spriteBatch)
+ {
+ Point checkPos = (Main.screenPosition + new Vector2(Main.screenWidth, Main.screenHeight) * 0.5f).ToTileCoordinates();
+ if (checkPos.X == i && checkPos.Y == j)
+ {
+ foreach (var hangingTile in TileLoader.tiles.OfType())
+ {
+ foreach (var tilePos in hangingTile.RopesOfAllThisTileInTheWorld.Keys)
+ {
+ var worldPos = tilePos.ToWorldCoordinates();
+ if (VFXManager.InScreen(worldPos, hangingTile.DrawOffScreenRange))
+ {
+ TileFluentDrawManager.AddFluentPoint(hangingTile, tilePos.X, tilePos.Y);
+ }
+ }
+ }
+ }
+ return base.PreDraw(i, j, type, spriteBatch);
+ }
+}
diff --git a/Sources/Everglow.Function/TileHelper/HangingExit.png b/Sources/Everglow.Function/TileHelper/HangingExit.png
new file mode 100644
index 000000000..3dc65a4b6
Binary files /dev/null and b/Sources/Everglow.Function/TileHelper/HangingExit.png differ
diff --git a/Sources/Everglow.Function/TileHelper/HangingTile.cs b/Sources/Everglow.Function/TileHelper/HangingTile.cs
index 03db6bb01..125019d4c 100644
--- a/Sources/Everglow.Function/TileHelper/HangingTile.cs
+++ b/Sources/Everglow.Function/TileHelper/HangingTile.cs
@@ -1,8 +1,6 @@
-using Everglow.Commons.Enums;
using Everglow.Commons.Physics.MassSpringSystem;
+using Everglow.Commons.Utilities;
using Everglow.Commons.Vertex;
-using Everglow.Commons.VFX;
-using Everglow.Commons.VFX.Pipelines;
using Terraria.Audio;
using Terraria.DataStructures;
using Terraria.GameContent.Drawing;
@@ -16,20 +14,19 @@ namespace Everglow.Commons.TileHelper;
///
public abstract class HangingTile : ModTile, ITileFluentlyDrawn
{
- public override string Texture => "Everglow/Commons/TileHelper/HangingWinch";
-
///
/// Max cable length : default 60
+ /// It means the max counts of rope units, not the max length in pixels.
///
public int MaxCableLength = 60;
///
- /// Lamp item mass : default 8
+ /// The mass of the hanging item(usually the light fixture at the bottom) : default 8
///
- public float SingleLampMass = 8;
+ public float HangingItemMass = 8;
///
- /// Cable mass : default 0.5f
+ /// Unit mass : default 0.5f
///
public float RopeUnitMass = 0.5f;
@@ -38,16 +35,86 @@ public abstract class HangingTile : ModTile, ITileFluentlyDrawn
///
public int MaxWireStyle = 2;
+ ///
+ /// The distance between joints when there is no external force.
+ ///
+ public float UnitLength = 6f;
+
///
/// Elasticity of cable : default 150
///
public float Elasticity = 150;
///
- /// Allow rotating joint to adjust length : default true
+ /// The maximum time (in frames) for the adjusting visual effect to last. default 60f.
+ ///
+ public float AdjustingVisualTimeMax = 60f;
+
+ ///
+ /// Allow right-click the top to adjust length : default true
///
public bool LengthAdjustable = true;
+ ///
+ /// If true, player can press "up" when passing the rope to grasp.
+ /// Then, player will absorb to the bottom of the rope and can swing on it.
+ ///
+ public bool CanGrasp = false;
+
+ ///
+ /// Be valid only when CanGrasp is true. default 48f. The range of detecting the rope tip when player press "up" to grasp.
+ ///
+ public float GraspDetectRange = 48f;
+
+ ///
+ /// How far should start drawing the rope in an area out of screen.
+ ///
+ public float DrawOffScreenRange = 1200f;
+
+ public string BulbTexturePath;
+
+ ///
+ ///
+ /// Winch position and rope.
+ /// 1 point contains 1 rope at most.
+ ///
+ public Dictionary RopesOfAllThisTileInTheWorld = new Dictionary();
+
+ ///
+ /// Current Player who is handling with the HangingTile winched at a certain Point.
+ /// 1 winch can be modified by only 1 player simultanrously.
+ ///
+ public Dictionary WinchAdjustingPlayers = new Dictionary();
+
+ ///
+ /// A mousePos-player Dictionary to prevent generating multiple knob VFX.
+ /// 1 winch can display more than 1 knob VFXs in multi-player mode.
+ ///
+ public Dictionary MouseOverWinchPlayers = new Dictionary();
+
+ ///
+ /// Current Player who grasping the rope of HangingTile winched at a certain Point.
+ /// Be valid only when CanGrasp is true.
+ /// 1 rope can be grasped by only 1 player.
+ ///
+ public static Dictionary RopeGraspingPlayer = new Dictionary();
+
+ public struct DrawStack
+ {
+ public Texture2D Texture;
+
+ public IEnumerable Vertices;
+
+ public PrimitiveType PType;
+
+ public DrawStack(Texture2D texture, IEnumerable vertices, PrimitiveType pType)
+ {
+ Texture = texture;
+ Vertices = vertices;
+ PType = pType;
+ }
+ }
+
public override void SetStaticDefaults()
{
Main.tileFrameImportant[Type] = true;
@@ -60,17 +127,57 @@ public override void SetStaticDefaults()
TileObjectData.newTile.UsesCustomCanPlace = true;
AddMapEntry(new Color(59, 67, 67));
+ InitHanging();
}
///
- /// Winch position and rope
+ /// Override to customize the values.
+ /// defaults:
+ /// MaxCableLength = 60;
+ /// HangingItemMass = 8;
+ /// RopeUnitMass = 0.5f;
+ /// MaxWireStyle = 2;
+ /// Elasticity = 150;
+ /// LengthAdjustable = true;
+ /// CanGrasp = false;
///
- public Dictionary RopesOfAllThisTileInTheWorld = new Dictionary();
+ public virtual void InitHanging()
+ {
+ }
+
+ ///
+ /// 在刚打开按钮时的行为
+ ///
+ /// HangingTile实例ä½ç½®
+ /// æ£åœ¨æ“作的玩家
+ public virtual void OnAdjustmentStart(Point fixPoint, Player player)
+ {
+ }
///
- /// Winch position and rope
+ /// 调整长度时的行为
///
- public Dictionary ChainPlayer = new Dictionary();
+ /// ä½ç½®åæ ‡
+ /// æ“作玩家
+ /// 长度增é‡,值为0代表这帧没å˜åŒ–,如果ä¸éœ€è¦å¤„ç†0请在值为0时直接return
+ public virtual void OnAdjustmentUpdate(Point fixPoint, Player player, int deltaLength)
+ {
+ Rope rope;
+ RopesOfAllThisTileInTheWorld.TryGetValue(fixPoint, out rope);
+ if (rope != null)
+ {
+ UpdateRopeAdjustment(rope, fixPoint);
+ }
+ }
+
+ ///
+ /// 结æŸè°ƒæ•´æ—¶çš„行为
+ ///
+ /// ä½ç½®åæ ‡
+ /// æ“作玩家
+ public virtual void OnAdjustmentEnd(Point fixPoint, Player player)
+ {
+ }
public override bool TileFrame(int i, int j, ref bool resetFrame, ref bool noBreak)
{
@@ -79,6 +186,12 @@ public override bool TileFrame(int i, int j, ref bool resetFrame, ref bool noBre
return base.TileFrame(i, j, ref resetFrame, ref noBreak);
}
+ public override void PlaceInWorld(int i, int j, Item item)
+ {
+ Tile tile = Main.tile[i, j];
+ tile.TileFrameY = 18;
+ }
+
public override void HitWire(int i, int j)
{
Tile tile = Main.tile[i, j];
@@ -88,7 +201,7 @@ public override void HitWire(int i, int j)
tile.TileFrameX = 0;
tile.TileFrameY += 18;
}
- int style = tile.TileFrameX / 18 + (tile.TileFrameY / 18) * 4;
+ int style = tile.TileFrameX / 18 + tile.TileFrameY / 18 * 4;
MaxWireStyle = Math.Min(MaxWireStyle, 16);
if (style >= MaxWireStyle)
{
@@ -108,7 +221,7 @@ public override void KillTile(int i, int j, ref bool fail, ref bool effectOnly,
}
///
- /// é è¿‘æ—¶æ ¹æ®TE挂绳
+ /// Add rope by TileEntity when approaching.
///
///
///
@@ -123,490 +236,534 @@ public override void NearbyEffects(int i, int j, bool closer)
}
///
- /// 挂上绳å
+ /// It should not check the grasping logic of players in any drawing function.
///
- ///
- ///
- ///
- public virtual void AddRope(int i, int j)
+ public virtual void CheckPlayerGrasp(Point pos)
{
- Rope rope = ConnectRope(i, j);
- if (rope == null)
+ Rope rope;
+ RopesOfAllThisTileInTheWorld.TryGetValue(pos, out rope);
+ if (rope is null)
{
return;
}
- if (RopesOfAllThisTileInTheWorld.ContainsKey(new Point(i, j)))
+ if (!RopeGraspingPlayer.ContainsKey(pos))
{
return;
}
- var masses = rope.Masses;
- RopesOfAllThisTileInTheWorld.Add(new Point(i, j), rope);
- TryGetCableEntityAs(i, j, out CableEneity cableEneity);
- if (cableEneity == null)
+ Player graspPlayer = RopeGraspingPlayer[pos];
+ if (graspPlayer is null)
{
- TileEntity.PlaceEntityNet(i, j, ModContent.TileEntityType());
- TryGetCableEntityAs(i, j, out cableEneity);
+ return;
}
- }
+ UpdateGraspingPlayer(graspPlayer, rope, pos);
- ///
- /// 挂绳
- ///
- ///
- ///
- ///
- ///
- ///
- public virtual Rope ConnectRope(int i, int j)
- {
- Tile tile = Main.tile[i, j];
- int counts = MaxCableLength;
- int restCount = tile.TileFrameY;
- Rope rope = Rope.Create_Fixed_Start_Heavy_End(new Point(i, j).ToWorldCoordinates(), counts, Elasticity, RopeUnitMass, SingleLampMass, MaxCableLength - restCount);
- return rope;
- }
-
- public override bool PreDraw(int i, int j, SpriteBatch spriteBatch)
- {
- Color lightColor = Lighting.GetColor(i, j);
- var zero = new Vector2(Main.offScreenRange, Main.offScreenRange);
- if (Main.drawToScreen)
+ if (!RopeGraspingPlayer.ContainsKey(pos) || RopeGraspingPlayer[pos] != graspPlayer)
{
- zero = Vector2.Zero;
+ return;
}
- spriteBatch.Draw(ModAsset.HangingWinch.Value, new Vector2(i, j) * 16 - Main.screenPosition + zero, new Rectangle(0, 0, 16, 16), lightColor, 0, Vector2.zeroVector, 1, SpriteEffects.None, 0);
-
- TileFluentDrawManager.AddFluentPoint(this, i, j);
- return false;
- }
-
- public override void DrawEffects(int i, int j, SpriteBatch spriteBatch, ref TileDrawInfo drawData)
- {
- base.DrawEffects(i, j, spriteBatch, ref drawData);
- }
- public void FluentDraw(Vector2 screenPosition, Point pos, SpriteBatch spriteBatch, TileDrawing tileDrawing)
- {
- Rope rope;
- RopesOfAllThisTileInTheWorld.TryGetValue(pos, out rope);
- if (rope != null)
+ // Check Remove Player
+ if (graspPlayer is null || !graspPlayer.active || graspPlayer.controlJump || graspPlayer.mount.Active)
{
- DrawCable(rope, pos, spriteBatch, tileDrawing);
+ RemovePlayerFromRope(graspPlayer, rope, pos);
}
}
- public string BulbTexturePath;
-
///
- /// 绘制挂物
+ /// Move the player.
+ /// Animate the player.
+ /// Swing the rope.
+ /// Check switch rope.
///
+ ///
///
///
- ///
- ///
- ///
- public virtual void DrawCable(Rope rope, Point pos, SpriteBatch spriteBatch, TileDrawing tileDrawing, Color color = default(Color))
+ public void UpdateGraspingPlayer(Player player, Rope rope, Point pos)
{
- // 回声涂料
- if (!TileDrawing.IsVisible(Main.tile[pos]))
+ var masses = rope.Masses;
+ var vineEndPosition = masses[^1].Position;
+
+ // Player Kinematics
+ player.Center = vineEndPosition;
+ player.velocity *= 0;
+ player.gravity *= 0;
+
+ // Player Animation
+ float rot = 0;
+ if (masses.Length > 2)
{
- return;
+ rot = (masses[^2].Position - masses[^1].Position).ToRotation() + MathHelper.PiOver2;
+ }
+ player.fullRotation = rot;
+ player.SetCompositeArmBack(true, Player.CompositeArmStretchAmount.Full, MathHelper.Pi);
+ if (!player.controlUseItem && !player.controlUseTile)
+ {
+ player.SetCompositeArmFront(true, Player.CompositeArmStretchAmount.Full, rot);
}
- var tile = Main.tile[pos];
- ushort type = tile.TileType;
- int paint = Main.tile[pos].TileColor;
- Texture2D tex = PaintedTextureSystem.TryGetPaintedTexture(BulbTexturePath, type, 1, paint, tileDrawing);
+ // Swing
+ Vector2 ropeDir = (masses[0].Position - masses[^1].Position).NormalizeSafe();
+ Vector2 pushDir = ropeDir.RotatedBy(MathHelper.PiOver2);
+ if (player.controlLeft && ropeDir.X < 0.6f)
+ {
+ PushRope(ref rope, -pushDir * 4);
+ }
+ if (player.controlRight && ropeDir.X > -0.6f)
+ {
+ PushRope(ref rope, pushDir * 4);
+ }
- // 获å–å‘绳端物å—ä¿¡æ¯
- var masses = rope.Masses;
- for (int i = 0; i < masses.Length; i++)
+ // Switch Ropes
+ if (player.controlDown)
{
- Mass thisMass = masses[i];
- if (i < MaxCableLength - tile.TileFrameY)
+ CheckSwitchRope(player, rope, pos);
+ }
+
+ // Collision
+ if (Collision.SolidCollision(player.position, player.width, player.height))
+ {
+ RemovePlayerFromRope(player, rope, pos);
+ }
+ if (player.controlHook)
+ {
+ RemovePlayerFromRope(player, rope, pos);
+ }
+ }
+
+ public void CheckSwitchRope(Player player, Rope rope, Point pos)
+ {
+ float minDistance = GraspDetectRange + 10;
+ Rope targetRope = null;
+ Point targetPoint = new Point(0, 0);
+ foreach (var hangingTile in TileLoader.tiles.OfType())
+ {
+ // Exclude the current type.
+ if (hangingTile == this)
{
- thisMass.IsStatic = true;
- thisMass.Position = pos.ToWorldCoordinates();
continue;
}
- else
- {
- thisMass.IsStatic = false;
- }
- int totalPushTime = 80;
- float pushForcePerFrame = 1.26f;
- float windCycle = 0;
- if (tileDrawing.InAPlaceWithWind((int)((thisMass.Position.X - 8) / 16f), (int)((thisMass.Position.Y - 8) / 16f), 1, 1))
- {
- windCycle = tileDrawing.GetWindCycle((int)((thisMass.Position.X - 8) / 16f), (int)((thisMass.Position.Y - 8) / 16f), tileDrawing._sunflowerWindCounter);
- }
-
- float highestWindGridPushComplex = tileDrawing.GetHighestWindGridPushComplex((int)((thisMass.Position.X - 8) / 16f), (int)((thisMass.Position.Y - 8) / 16f), 1, 1, totalPushTime, pushForcePerFrame, 3, swapLoopDir: true);
- windCycle += highestWindGridPushComplex;
- if (!Main.gamePaused)
+ bool findCloser = false;
+ foreach (var rope_new in hangingTile.RopesOfAllThisTileInTheWorld.Values)
{
- if (i < masses.Length - 1)
- {
- rope.ApplyForceSpecial(i, new Vector2(windCycle / 4.0f, 0.4f * thisMass.Value));
- }
- else
+ Vector2 ropeTipPos = rope_new.Masses.Last().Position;
+ Vector2 playerToTip = ropeTipPos - player.Center;
+ if (playerToTip.Length() < minDistance)
{
- rope.ApplyForceSpecial(i, new Vector2(windCycle * 10.0f, 0.4f * thisMass.Value));
+ minDistance = playerToTip.Length();
+ targetRope = rope_new;
+ findCloser = true;
}
}
-
- // 支æŒå‘光涂料
- Color tileLight;
- if (color != default)
- {
- tileLight = color;
- }
- else
- {
- tileLight = Lighting.GetColor((int)((thisMass.Position.X - 8) / 16f), (int)((thisMass.Position.Y - 8) / 16f));
- }
-
- Vector2 toNextMass;
- if (i < masses.Length - 1)
+ if (findCloser)
{
- Mass nextMass = masses[i + 1];
- toNextMass = nextMass.Position - thisMass.Position;
+ targetPoint = hangingTile.RopesOfAllThisTileInTheWorld.FirstOrDefault(kv => kv.Value == targetRope).Key;
}
- else
+ }
+ foreach (var rope_new in RopesOfAllThisTileInTheWorld.Values)
+ {
+ // Exclude the current rope.
+ if (RopesOfAllThisTileInTheWorld.ContainsKey(pos) && RopesOfAllThisTileInTheWorld[pos] == rope_new)
{
- Mass passedMass = masses[i - 1];
- toNextMass = thisMass.Position - passedMass.Position;
+ continue;
}
- Vector2 drawPos = thisMass.Position - Main.screenPosition;
- if (i < masses.Length - 1)
+ bool findCloser = false;
+ Vector2 ropeTipPos = rope_new.Masses.Last().Position;
+ Vector2 playerToTip = ropeTipPos - player.Center;
+ if (playerToTip.Length() < minDistance)
{
- spriteBatch.Draw(tex, drawPos, new Rectangle(8 * (i % 4), 0, 8, 10), tileLight, toNextMass.ToRotation() - MathHelper.PiOver2, new Vector2(4f, 0), 1f, SpriteEffects.None, 0);
+ minDistance = playerToTip.Length();
+ targetRope = rope_new;
+ findCloser = true;
}
- else
+ if (findCloser)
{
- spriteBatch.Draw(tex, drawPos, new Rectangle(0, 12, 32, 40), tileLight, toNextMass.ToRotation() - MathHelper.PiOver2, new Vector2(16f, 0), 1f, SpriteEffects.None, 0);
- Lighting.AddLight(drawPos + Main.screenPosition, new Vector3(0.8f, 0.8f, 0.2f));
+ targetPoint = RopesOfAllThisTileInTheWorld.FirstOrDefault(kv => kv.Value == targetRope).Key;
}
}
+ if (targetRope is null)
+ {
+ return;
+ }
+ RemovePlayerFromRope(player, rope, pos);
+ AddPlayerToRope(player, targetRope, targetPoint);
}
- ///
- /// Try to get the cable entity bound at (, ).
- ///
- /// The type to get the entity as
- /// The tile X-coordinate
- /// The tile Y-coordinate
- /// The found instance, if there was one.
- /// if there was a instance, or if there was no entity present OR the entity was not a instance.
- public static bool TryGetCableEntityAs(int i, int j, out T entity)
- where T : TileEntity
+ public void AddPlayerToRope(Player player, Rope rope, Point tilePos)
{
- Point16 origin = new Point16(i, j);
-
- // TileEntity.ByPosition is a Dictionary which contains all placed TileEntity instances in the world
- // TryGetValue is used to both check if the dictionary has the key, origin, and get the value from that key if it's there
- if (TileEntity.ByPosition.TryGetValue(origin, out TileEntity existing) && existing is T existingAsT)
+ HangingTile_Player hTP = player.GetModPlayer();
+ if (hTP is null)
{
- entity = existingAsT;
- return true;
+ return;
+ }
+ if (hTP.SwitchVineCoolTimer > 0)
+ {
+ return;
+ }
+ hTP.SwitchVineCoolTimer = 30;
+ if (RopeGraspingPlayer.TryAdd(tilePos, player))
+ {
+ hTP.Grasping = true;
+ PushRope(ref rope, player.velocity * 12f);
+ player.RemoveAllGrapplingHooks();
}
+ }
- entity = null;
- return false;
+ public void RemovePlayerFromRope(Player player, Rope rope, Point tilePos)
+ {
+ HangingTile_Player hTP = player.GetModPlayer();
+ if (hTP is null)
+ {
+ return;
+ }
+ if (hTP.SwitchVineCoolTimer > 0)
+ {
+ return;
+ }
+ hTP.Grasping = false;
+ var masses = rope.Masses;
+ RopeGraspingPlayer.Remove(tilePos);
+ player.gravity = Player.defaultGravity;
+ Vector2 finalVel = masses[^1].Velocity * 3;
+ player.velocity = finalVel;
+ PushRope(ref rope, -finalVel * 16f);
+ player.fullRotation = 0f;
}
///
- /// é¼ æ ‡åˆ’è¿‡ç‚¹ä½
+ /// Apply a force to the whole rope.
///
- public Dictionary MouseOverPoint = new Dictionary();
-
- public override void MouseOver(int i, int j)
+ ///
+ ///
+ public void PushRope(ref Rope rope, Vector2 force)
{
- if (LengthAdjustable)
+ var masses = rope.Masses;
+ for (int i = 0; i < masses.Length; i++)
{
- if (!MouseOverPoint.ContainsKey(Main.LocalPlayer))
- {
- MouseOverPoint.Add(Main.LocalPlayer, new Point(i, j));
- if (Main.LocalPlayer.HeldItem.createTile == Type)
- {
- HangingTileLengthAdjustingSystem vfx = new HangingTileLengthAdjustingSystem { FixPoint = new Point(i, j), Active = true, Visible = true, Style = 0 };
- Ins.VFXManager.Add(vfx);
- }
- }
- else if (MouseOverPoint[Main.LocalPlayer] != new Point(i, j))
- {
- MouseOverPoint.Remove(Main.LocalPlayer);
- }
+ float value = i / (float)masses.Length;
+ rope.ApplyForceSpecial(i, value * force);
}
}
///
- /// Right click to adjust cable length.
+ /// Add the rope.
///
///
///
- ///
- public override bool RightClick(int i, int j)
+ ///
+ public virtual void AddRope(int i, int j)
{
- if (LengthAdjustable)
+ Point pos = new Point(i, j);
+ Tile tile = Main.tile[pos];
+ int counts = MaxCableLength;
+ int restCount = tile.TileFrameY;
+ Rope rope = Rope.Create_Fixed_Start_Heavy_End(pos.ToWorldCoordinates(), counts, Elasticity, RopeUnitMass, HangingItemMass, MaxCableLength - restCount, UnitLength);
+ if (rope == null)
{
- // 旋转
- Tile tile = Main.tile[i, j];
- if (Main.LocalPlayer.HeldItem.createTile == Main.tile[i, j].TileType && !ChainPlayer.ContainsKey(new Point(i, j)))
- {
- HangingTileLengthAdjustingSystem vfx = new HangingTileLengthAdjustingSystem { FixPoint = new Point(i, j), Active = true, Visible = true, Style = 1, StartFrameY60 = tile.TileFrameY * 60 };
- Ins.VFXManager.Add(vfx);
- SoundEngine.PlaySound(SoundID.Item17, new Vector2(i, j) * 16);
- ChainPlayer.Add(new Point(i, j), Main.LocalPlayer);
- }
+ return;
}
- return base.RightClick(i, j);
- }
+ if (RopesOfAllThisTileInTheWorld.ContainsKey(pos))
+ {
+ return;
+ }
+ RopesOfAllThisTileInTheWorld.Add(pos, rope);
+ TryGetCableEntityAs(i, j, out CableEneity cableEneity);
+ if (cableEneity == null)
+ {
+ TileEntity.PlaceEntityNet(i, j, ModContent.TileEntityType());
+ TryGetCableEntityAs(i, j, out cableEneity);
+ }
+ UpdateRopeAdjustment(rope, pos);
- public override void PlaceInWorld(int i, int j, Item item)
- {
- Tile tile = Main.tile[i, j];
- tile.TileFrameY = 18;
+ // Initialize the positions of masses.
+ var masses = rope.Masses;
+ Vector2 currentPos = Vector2.zeroVector;
+ for (int k = 0; k < masses.Length; k++)
+ {
+ Mass thisMass = masses[k];
+ if (!thisMass.IsStatic)
+ {
+ currentPos += new Vector2(0, UnitLength);
+ masses[k].Position = pos.ToWorldCoordinates() + currentPos;
+ }
+ }
}
-}
-[Pipeline(typeof(WCSPipeline))]
-public class HangingTileLengthAdjustingSystem : Visual
-{
- public override CodeLayer DrawLayer => CodeLayer.PreDrawFilter;
-
- public Texture2D Texture;
- public Point FixPoint;
- public int Style;
- public float StartFrameY60;
- public Vector2 StartRotation;
- public float AccumulateRotation;
- public Vector2 OldRotation;
-
- public override void OnSpawn()
+ ///
+ /// Highlight a knob which can adjust the rope.
+ ///
+ ///
+ ///
+ public override void MouseOver(int i, int j)
{
- StartRotation = Utils.SafeNormalize(FixPoint.ToWorldCoordinates() - Main.MouseWorld, new Vector2(0, -1));
- OldRotation = StartRotation;
- AccumulateRotation = 0;
- Texture = ModAsset.TileBlock.Value;
+ base.MouseOver(i, j);
}
- public override void Update()
+ public override void MouseOverFar(int i, int j)
{
Player player = Main.LocalPlayer;
- int i = FixPoint.X;
- int j = FixPoint.Y;
- if (i < 20 || i > Main.maxTilesX - 20)
+ Point point = new Point(i, j);
+ if (!IsCanRightClick(i, j))
{
- if (j < 20 || j > Main.maxTilesY - 20)
- {
- Active = false;
- return;
- }
+ return;
}
- Tile tile = Main.tile[i, j];
- HangingTile hangingTile = TileLoader.GetTile(tile.type) as HangingTile;
- if (hangingTile == null)
+ if (LengthAdjustable && !RopeGraspingPlayer.ContainsKey(point))
{
- Active = false;
- return;
+ if (!MouseOverWinchPlayers.ContainsKey(player) && TileUtils.CanPlayerInteractWithTile(i, j, player))
+ {
+ MouseOverWinchPlayers.Add(player, point);
+ HangingTileAdjustingHelper vfx = new HangingTileAdjustingHelper { FixPoint = point, Active = true, Visible = true, Style = 0 };
+ Ins.VFXManager.Add(vfx);
+ }
+ else if (MouseOverWinchPlayers[player] != point)
+ {
+ MouseOverWinchPlayers.Remove(player);
+ }
+ if (MouseOverWinchPlayers.ContainsKey(player))
+ {
+ if (Main.mouseRight && Main.mouseRightRelease)
+ {
+ if (LengthAdjustable && !RopeGraspingPlayer.ContainsKey(point))
+ {
+ Tile tile = Main.tile[point];
+ if (!WinchAdjustingPlayers.ContainsKey(point))
+ {
+ OnAdjustmentStart(point, Main.LocalPlayer);
+ HangingTileUpdateSystem.WinchAdjustingPlayerTimers[point] = AdjustingVisualTimeMax;
+ HangingTileAdjustingHelper vfx = new HangingTileAdjustingHelper { FixPoint = point, Active = true, Visible = true, Style = 1, StartFrameY60 = tile.TileFrameY * 60 };
+ vfx.RegisterCustomPanelDrawing(DrawDefaultPanel);
+ vfx.HandleRotation = (point.ToWorldCoordinates() - player.MouseWorld()).ToRotationSafe();
+ vfx.InitialHandleRotation = vfx.HandleRotation;
+ vfx.Timer = 0;
+ Ins.VFXManager.Add(vfx);
+ SoundEngine.PlaySound(SoundID.Item17, point.ToWorldCoordinates());
+ WinchAdjustingPlayers.Add(point, Main.LocalPlayer);
+ AdjustingVisualTimeMax = 30;
+ }
+ else
+ {
+ WinchAdjustingPlayers.Remove(point);
+ }
+ }
+ }
+ }
}
- if (hangingTile.ChainPlayer.ContainsKey(FixPoint))
+ }
+
+ ///
+ /// Right click to adjust cable length.
+ ///
+ ///
+ ///
+ ///
+ public override bool RightClick(int i, int j)
+ {
+ return base.RightClick(i, j);
+ }
+
+ ///
+ /// 基于å³é”®å®žçŽ°è°ƒæ•´ç»³åé•¿åº¦çš„åŠŸèƒ½ï¼Œä½ å¯ä»¥è‡ªå®šä¹‰å¼€å¯è°ƒæ•´æ—‹é’®çš„æ¡ä»¶ï¼Œé»˜è®¤å½“æ‰‹æŒç‰©å“å’Œå³é”®ç‰©å—ç±»åž‹ç›¸åŒæ—¶è¿”回true。
+ ///
+ /// å³é”®ä½ç½®çš„æ¨ªåæ ‡
+ /// å³é”®ä½ç½®çš„çºµåæ ‡
+ /// 值为true表示å…è®¸å¼€å¯æ—‹é’®
+ public virtual bool IsCanRightClick(int i, int j)
+ {
+ return Main.LocalPlayer.HeldItem.createTile == Main.tile[i, j].TileType;
+ }
+
+ ///
+ /// The drawing part of the rope-adjusting-knob. é‡å†™æˆ‘æ¥é‡ç»˜æŒ‰é’®æ•ˆæžœ
+ ///
+ ///
+ ///
+ ///
+ ///
+ public virtual void DrawDefaultPanel(HangingTileAdjustingHelper hangingSystem, Player player, Color color, ref Queue drawStacks)
+ {
+ drawStacks = new Queue();
+ DrawBackgroundPanel(hangingSystem, Color.White * 0.5f, ref drawStacks);
+ float maxCos = 0;
+ int maxK = 0;
+ Vector2 rotCenter = hangingSystem.FixPoint.ToWorldCoordinates();
+ Vector2 cut = new Vector2(1, 0).RotatedBy(hangingSystem.HandleRotation + MathHelper.Pi);
+
+ // Calculate the bloom effect of calibration tails.
+ for (int k = -10; k < 10; k++)
{
- Player player2;
- hangingTile.ChainPlayer.TryGetValue(FixPoint, out player2);
- if (player2 != player)
+ Vector2 cut2 = new Vector2(0, -1).RotatedBy(k / 20f * MathHelper.TwoPi);
+ float cosValue = Vector2.Dot(cut, cut2);
+ if (cosValue > maxCos)
{
- KillMe(hangingTile, player);
- return;
+ maxCos = cosValue;
+ maxK = k;
}
}
- if (player.HeldItem.createTile != tile.TileType)
+
+ // Draw calibration tails.
+ Color newDrawColor = color;
+ float nowFrameY = hangingSystem.StartFrameY60 / 60f + hangingSystem.HandleRotation * 2;
+ if (nowFrameY < 5)
{
- KillMe(hangingTile, player);
- return;
+ newDrawColor = Color.Lerp(color, new Color(1f, 0f, 0f, 0.8f), (5 - nowFrameY) / 4f);
}
- if ((Main.MouseWorld - FixPoint.ToWorldCoordinates()).Length() > 400)
+ if (nowFrameY > MaxCableLength - 5)
{
- KillMe(hangingTile, player);
- return;
+ newDrawColor = Color.Lerp(color, new Color(1f, 0f, 0f, 0.8f), (nowFrameY - (MaxCableLength - 5)) / 4f);
}
- if (Style == 0)
+ float tK = 12f;
+ if (hangingSystem.TimeToKill > 0)
{
- int x = (int)(Main.MouseWorld.X / 16f);
- int y = (int)(Main.MouseWorld.Y / 16f);
- if (x != FixPoint.X || y != FixPoint.Y)
- {
- Active = false;
- if (hangingTile.MouseOverPoint.ContainsKey(player))
- {
- hangingTile.MouseOverPoint.Remove(player);
- }
- return;
- }
+ tK = hangingSystem.TimeToKill;
}
- if (Style == 1)
+ float fade = Math.Min(hangingSystem.Timer, tK) / 12f;
+ for (int k = -10; k < 10; k++)
{
- if (!hangingTile.ChainPlayer.ContainsKey(FixPoint))
- {
- KillMe(hangingTile, player);
- return;
- }
- if (!hangingTile.ChainPlayer.ContainsKey(FixPoint))
- {
- KillMe(hangingTile, player);
- return;
- }
- float addAccRot = MathF.Asin(-Vector3.Cross(new Vector3(Utils.SafeNormalize(FixPoint.ToWorldCoordinates() - Main.MouseWorld, new Vector2(0, -1)), 0), new Vector3(OldRotation, 0)).Z);
- AccumulateRotation += addAccRot;
- OldRotation = Utils.SafeNormalize(FixPoint.ToWorldCoordinates() - Main.MouseWorld, new Vector2(0, -1));
- float nowFrameY = StartFrameY60 / 60f + AccumulateRotation * 2;
- if (nowFrameY < 1)
- {
- AccumulateRotation -= addAccRot;
- }
- if (nowFrameY > hangingTile.MaxCableLength - 1)
+ Vector2 cut2 = new Vector2(0, -1).RotatedBy(k / 20f * MathHelper.TwoPi);
+ float cosValue = Vector2.Dot(cut, cut2);
+
+ if (k == maxK)
{
- AccumulateRotation -= addAccRot;
+ DrawLine_Black(hangingSystem, rotCenter + cut2 * (4 * hangingSystem.PanelRange - 12), rotCenter + cut2 * (4 * hangingSystem.PanelRange + 36), 16, ref drawStacks);
+ DrawLine(rotCenter + cut2 * (4 * hangingSystem.PanelRange - 12), rotCenter + cut2 * (4 * hangingSystem.PanelRange + 36), 16, newDrawColor * fade, 1f, ref drawStacks);
}
- bool endChain = false;
- if (nowFrameY < 2)
+ else
{
- endChain = true;
+ DrawLine(rotCenter + cut2 * 4 * hangingSystem.PanelRange, rotCenter + cut2 * (4 * hangingSystem.PanelRange + 24), 12, newDrawColor * fade, cosValue, ref drawStacks);
}
- if (nowFrameY > hangingTile.MaxCableLength - 2)
+ }
+
+ // Draw bound.
+ DrawBound(hangingSystem, color, player, ref drawStacks);
+ DrawDirectionRing(hangingSystem, newDrawColor, hangingSystem.HandleRotation - MathHelper.PiOver2, ref drawStacks);
+ }
+
+ public virtual void DrawBound(HangingTileAdjustingHelper hangingSystem, Color color, Player player, ref Queue drawStacks)
+ {
+ if (drawStacks == null)
+ {
+ drawStacks = new Queue();
+ }
+ Vector2 rotCenter = hangingSystem.FixPoint.ToWorldCoordinates();
+ if ((player.MouseWorld() - rotCenter).Length() > 240)
+ {
+ Vector2 cut3 = (player.MouseWorld() - rotCenter).NormalizeSafe();
+ float colorValue = ((player.MouseWorld() - rotCenter).Length() - 240f) / 160f;
+ colorValue = Math.Min(colorValue, 1);
+ Color newDrawColor = Color.Lerp(color, new Color(1f, 0f, 0f, 0f), colorValue);
+ newDrawColor.A = 0;
+ float colorFade = 1f;
+ if (hangingSystem.TimeToKill > 0)
{
- endChain = true;
+ colorFade = hangingSystem.TimeToKill / 12f;
}
- if (tile.TileFrameY != (short)Math.Clamp(nowFrameY, 1, hangingTile.MaxCableLength - 1))
+ Color backgroundColor = Color.White * 0.6f * colorFade;
+ newDrawColor *= colorFade;
+ Main.instance.MouseText("Drag out of circle to cancel", ItemRarityID.White);
+
+ List bars_left = new List();
+ List bars_right = new List();
+
+ List bars_left_black = new List();
+ List bars_right_black = new List();
+ for (int k = 0; k < 30; k++)
{
- if (!endChain)
- {
- SoundEngine.PlaySound(SoundID.Unlock.WithVolume(0.5f), FixPoint.ToWorldCoordinates());
- }
- tile.TileFrameY = (short)Math.Clamp(nowFrameY, 1, hangingTile.MaxCableLength - 1);
+ float xCoord = (colorValue - k / 30f) * 0.8f;
+ xCoord = Math.Clamp(xCoord, 0, 1);
+ bars_left_black.Add(rotCenter + cut3.RotatedBy(k / 30f) * 400f, backgroundColor, new Vector3(xCoord, 0.5f, 0));
+ bars_left_black.Add(rotCenter + cut3.RotatedBy(k / 30f) * 350f, backgroundColor, new Vector3(xCoord, 0.8f, 0));
+
+ bars_right_black.Add(rotCenter + cut3.RotatedBy(-k / 30f) * 400f, backgroundColor, new Vector3(xCoord, 0.5f, 0));
+ bars_right_black.Add(rotCenter + cut3.RotatedBy(-k / 30f) * 350f, backgroundColor, new Vector3(xCoord, 0.8f, 0));
+
+ bars_left.Add(rotCenter + cut3.RotatedBy(k / 30f) * 400f, newDrawColor, new Vector3(xCoord, 0.5f, 0));
+ bars_left.Add(rotCenter + cut3.RotatedBy(k / 30f) * 350f, newDrawColor, new Vector3(xCoord, 0.8f, 0));
+
+ bars_right.Add(rotCenter + cut3.RotatedBy(-k / 30f) * 400f, newDrawColor, new Vector3(xCoord, 0.5f, 0));
+ bars_right.Add(rotCenter + cut3.RotatedBy(-k / 30f) * 350f, newDrawColor, new Vector3(xCoord, 0.8f, 0));
}
- int x = (int)(Main.MouseWorld.X / 16f);
- int y = (int)(Main.MouseWorld.Y / 16f);
- if (Main.mouseRight && Main.mouseRightRelease && (x != FixPoint.X || y != FixPoint.Y))
+ drawStacks.Enqueue(new DrawStack(ModAsset.SparkDark.Value, bars_left_black, PrimitiveType.TriangleStrip));
+ drawStacks.Enqueue(new DrawStack(ModAsset.SparkDark.Value, bars_right_black, PrimitiveType.TriangleStrip));
+
+ drawStacks.Enqueue(new DrawStack(ModAsset.SparkLight.Value, bars_left, PrimitiveType.TriangleStrip));
+ drawStacks.Enqueue(new DrawStack(ModAsset.SparkLight.Value, bars_right, PrimitiveType.TriangleStrip));
+
+ List text_bars = new List();
+ Color textColor = Color.White;
+ for (int k = -30; k < 30; k++)
{
- KillMe(hangingTile, player);
- return;
+ float xCoord = -k / 15f;
+ float fade = (30 * colorValue - Math.Abs(k)) / 15f;
+ fade = Math.Clamp(fade, 0f, 1f);
+ fade = MathF.Sin(fade);
+ text_bars.Add(rotCenter + cut3.RotatedBy(k / 30f) * 420f, textColor * fade * colorFade, new Vector3(xCoord, 1f, 0));
+ text_bars.Add(rotCenter + cut3.RotatedBy(k / 30f) * 400f, textColor * fade * colorFade, new Vector3(xCoord, 0f, 0));
}
+ drawStacks.Enqueue(new DrawStack(ModAsset.HangingExit.Value, text_bars, PrimitiveType.TriangleStrip));
}
- base.Update();
}
- public void KillMe(HangingTile hangingTile, Player owner)
+ public virtual void DrawDirectionRing(HangingTileAdjustingHelper hangingSystem, Color color, float rotation, ref Queue drawStacks)
{
- Active = false;
- if (hangingTile.MouseOverPoint.ContainsKey(owner))
+ if (drawStacks == null)
{
- hangingTile.MouseOverPoint.Remove(owner);
+ drawStacks = new Queue();
}
- if (hangingTile.ChainPlayer.ContainsKey(FixPoint))
+ color.A = 0;
+ Vector2 pos = hangingSystem.FixPoint.ToWorldCoordinates();
+ List bars = new List();
+ for (int k = 0; k <= 60; k++)
{
- hangingTile.ChainPlayer.Remove(FixPoint);
+ bars.Add(pos + new Vector2(0, hangingSystem.PanelRange * 24).RotatedBy(k / 60f * MathHelper.TwoPi + rotation), color, new Vector3(0.5f, k / 15f, 0));
+ bars.Add(pos + new Vector2(0, hangingSystem.PanelRange * 0).RotatedBy(k / 60f * MathHelper.TwoPi + rotation), color, new Vector3(0.3f, k / 15f, 0));
}
- }
-
- public override void Draw()
- {
- int i = FixPoint.X;
- int j = FixPoint.Y;
- if (i < 20 || i > Main.maxTilesX - 20)
+ drawStacks.Enqueue(new DrawStack(ModAsset.StarSlash.Value, bars, PrimitiveType.TriangleStrip));
+ bars = new List();
+ for (int k = 0; k <= 60; k++)
{
- if (j < 20 || j > Main.maxTilesY - 20)
- {
- Active = false;
- return;
- }
+ bars.Add(pos + new Vector2(0, hangingSystem.PanelRange * 12).RotatedBy(k / 60f * MathHelper.TwoPi + rotation), color, new Vector3(0.5f, k / 30f, 0));
+ bars.Add(pos + new Vector2(0, hangingSystem.PanelRange * 0).RotatedBy(k / 60f * MathHelper.TwoPi + rotation), color, new Vector3(0.3f, k / 30f, 0));
}
- Player player = Main.LocalPlayer;
- Tile tile = Main.tile[i, j];
- HangingTile hangingTile = TileLoader.GetTile(tile.type) as HangingTile;
- if (hangingTile == null)
+ drawStacks.Enqueue(new DrawStack(ModAsset.StarSlash.Value, bars, PrimitiveType.TriangleStrip));
+ bars = new List();
+ for (int k = 0; k <= 60; k++)
{
- Active = false;
- return;
+ bars.Add(pos + new Vector2(0, hangingSystem.PanelRange * 22).RotatedBy(k / 60f * MathHelper.TwoPi + rotation), color, new Vector3(0.5f, k / 60f, 0));
+ bars.Add(pos + new Vector2(0, hangingSystem.PanelRange * 12).RotatedBy(k / 60f * MathHelper.TwoPi + rotation), color, new Vector3(0.3f, k / 60f, 0));
}
- Color drawColor = Color.Lerp(new Color(0.75f, 0.75f, 1f, 0.5f), new Color(0.85f, 0.85f, 0.75f, 0.5f), MathF.Sin((float)Main.timeForVisualEffects * 0.08f) * 0.5f + 0.5f);
- Color origDrawColor = drawColor;
- if (Style == 1)
+ drawStacks.Enqueue(new DrawStack(ModAsset.StarSlash.Value, bars, PrimitiveType.TriangleStrip));
+ bars = new List();
+ for (int k = 0; k <= 60; k++)
{
- float nowFrameY = StartFrameY60 / 60f + AccumulateRotation * 2;
- if (nowFrameY < 5)
- {
- drawColor = Color.Lerp(drawColor, new Color(1f, 0f, 0f, 0.8f), (5 - nowFrameY) / 4f);
- }
- if (nowFrameY > hangingTile.MaxCableLength - 5)
- {
- drawColor = Color.Lerp(drawColor, new Color(1f, 0f, 0f, 0.8f), (nowFrameY - (hangingTile.MaxCableLength - 5)) / 4f);
- }
+ bars.Add(pos + new Vector2(0, hangingSystem.PanelRange * 26).RotatedBy(k / 60f * MathHelper.TwoPi + rotation), color, new Vector3(0.5f, 0.5f, 0));
+ bars.Add(pos + new Vector2(0, hangingSystem.PanelRange * 24).RotatedBy(k / 60f * MathHelper.TwoPi + rotation), color, new Vector3(0.5f, 0.5f, 0));
}
+ drawStacks.Enqueue(new DrawStack(ModAsset.StarSlash.Value, bars, PrimitiveType.TriangleStrip));
+ }
- // ä¸åŒç§ç±»ç‰©å—æ ‡çº¢
- if (player.HeldItem.createTile != tile.type)
+ public virtual void DrawBackgroundPanel(HangingTileAdjustingHelper hangingSystem, Color color, ref Queue drawStacks)
+ {
+ if (drawStacks == null)
{
- drawColor = new Color(1f, 0, 0, 0.5f);
- Main.instance.MouseText("Different Type Error", ItemRarityID.Red);
+ drawStacks = new Queue();
}
- Ins.Batch.BindTexture(Texture);
-
- Vector2 rotCenter = FixPoint.ToWorldCoordinates();
- Vector2 cut = -Utils.SafeNormalize(rotCenter - Main.MouseWorld, new Vector2(0, -1));
- if (hangingTile.RopesOfAllThisTileInTheWorld.ContainsKey(FixPoint))
+ Vector2 pos = hangingSystem.FixPoint.ToWorldCoordinates();
+ List bars = new List();
+ for (int k = 0; k <= 60; k++)
{
- if (Style == 1)
- {
- float maxCos = 0;
- int maxK = 0;
- for (int k = -10; k < 10; k++)
- {
- Vector2 cut2 = new Vector2(0, -1).RotatedBy(k / 20f * MathHelper.TwoPi);
- float cosValue = Vector2.Dot(cut, cut2);
- if (cosValue > maxCos)
- {
- maxCos = cosValue;
- maxK = k;
- }
- Color newDrawColor = origDrawColor;
- float thisFrameY = StartFrameY60 / 60f + (AccumulateRotation + k / 20f * MathHelper.TwoPi) * 2;
- if (thisFrameY < 5)
- {
- newDrawColor = Color.Lerp(origDrawColor, new Color(1f, 0f, 0f, 0.8f), (5 - thisFrameY) / 4f);
- }
- if (thisFrameY > hangingTile.MaxCableLength - 5)
- {
- newDrawColor = Color.Lerp(origDrawColor, new Color(1f, 0f, 0f, 0.8f), (thisFrameY - (hangingTile.MaxCableLength - 5)) / 4f);
- }
- DrawLine(rotCenter + cut2 * 15, rotCenter + cut2 * 20, 1.5f, newDrawColor);
- }
- Vector2 cut3 = new Vector2(0, -1).RotatedBy(maxK / 20f * MathHelper.TwoPi);
- DrawLine(rotCenter + cut3 * 12, rotCenter + cut3 * 26, 2, drawColor);
- if ((Main.MouseWorld - rotCenter).Length() > 240)
- {
- for (int k = -10; k < 10; k++)
- {
- Vector2 cut4 = cut.RotatedBy((k - 0.5f) * 0.04f);
- Vector2 cut5 = cut.RotatedBy((k + 0.5f) * 0.04f);
- float colorValue = ((Main.MouseWorld - rotCenter).Length() - 240f) / 160f;
- Color newDrawColor = origDrawColor;
- newDrawColor = Color.Lerp(origDrawColor, new Color(1f, 0f, 0f, 0.8f), colorValue);
- colorValue *= (100f - k * k) / 100f;
- DrawLine(rotCenter + cut4 * 390f, rotCenter + cut5 * 390f, 2f, newDrawColor * colorValue * 2);
- }
- Main.instance.MouseText("Drag out of circle to cancel", ItemRarityID.White);
- }
- }
+ bars.Add(pos + new Vector2(0, hangingSystem.PanelRange * 70).RotatedBy(k / 60f * MathHelper.TwoPi), color, new Vector3(k / 60f, 0, 0));
+ bars.Add(pos + new Vector2(0, hangingSystem.PanelRange * 0).RotatedBy(k / 60f * MathHelper.TwoPi), color, new Vector3(k / 60f, 0.5f, 0));
}
- DrawBlockBound(FixPoint.X, FixPoint.Y, drawColor, AccumulateRotation);
+ drawStacks.Enqueue(new DrawStack(ModAsset.Trail_7_black.Value, bars, PrimitiveType.TriangleStrip));
}
- public void DrawBlockBound(int i, int j, Color color, float rotation)
+ public virtual void DrawBlockBound(HangingTileAdjustingHelper hangingSystem, Color color, float rotation, ref Queue drawStacks)
{
- Vector2 pos = new Vector2(i, j) * 16 + new Vector2(8);
+ if (drawStacks == null)
+ {
+ drawStacks = new Queue();
+ }
+ Vector2 pos = hangingSystem.FixPoint.ToWorldCoordinates();
List bars = new List()
{
new Vertex2D(pos + new Vector2(-8, -8).RotatedBy(rotation), color, new Vector3(0, 0, 0)),
@@ -617,65 +774,288 @@ public void DrawBlockBound(int i, int j, Color color, float rotation)
new Vertex2D(pos + new Vector2(8, -8).RotatedBy(rotation), color, new Vector3(1, 0, 0)),
new Vertex2D(pos + new Vector2(8, 8).RotatedBy(rotation), color, new Vector3(1, 1, 0)),
};
-
- Ins.Batch.Draw(bars, PrimitiveType.TriangleList);
+ drawStacks.Enqueue(new DrawStack(ModAsset.TileBlock.Value, bars, PrimitiveType.TriangleList));
}
- public void DrawLine(Vector2 pos1, Vector2 pos2, float width, Color color)
+ public virtual void DrawLine(Vector2 pos1, Vector2 pos2, float width, Color color, float highlight, ref Queue drawStacks)
{
+ if (drawStacks == null)
+ {
+ drawStacks = new Queue();
+ }
Vector2 normal = Utils.SafeNormalize(pos1 - pos2, Vector2.zeroVector).RotatedBy(MathHelper.PiOver2) * width / 2f;
List bars = new List()
{
new Vertex2D(pos1 + normal, color, new Vector3(0, 0, 0)),
- new Vertex2D(pos2 + normal, color, new Vector3(0.1f, 0, 0)),
+ new Vertex2D(pos2 + normal, color, new Vector3(1, 0, 0)),
new Vertex2D(pos1 - normal, color, new Vector3(0, 1, 0)),
new Vertex2D(pos1 - normal, color, new Vector3(0, 1, 0)),
- new Vertex2D(pos2 + normal, color, new Vector3(0.1f, 0, 0)),
- new Vertex2D(pos2 - normal, color, new Vector3(0.1f, 1, 0)),
+ new Vertex2D(pos2 + normal, color, new Vector3(1, 0, 0)),
+ new Vertex2D(pos2 - normal, color, new Vector3(1, 1, 0)),
};
+ drawStacks.Enqueue(new DrawStack(ModAsset.SquarePiece.Value, bars, PrimitiveType.TriangleList));
+ if (highlight > 0)
+ {
+ Color bloomColor = color * highlight;
+ bloomColor.A = 0;
+ bars = new List()
+ {
+ new Vertex2D(pos1 + normal, bloomColor, new Vector3(0, 0, 0)),
+ new Vertex2D(pos2 + normal, bloomColor, new Vector3(1, 0, 0)),
+ new Vertex2D(pos1 - normal, bloomColor, new Vector3(0, 1, 0)),
- Ins.Batch.Draw(bars, PrimitiveType.TriangleList);
+ new Vertex2D(pos1 - normal, bloomColor, new Vector3(0, 1, 0)),
+ new Vertex2D(pos2 + normal, bloomColor, new Vector3(1, 0, 0)),
+ new Vertex2D(pos2 - normal, bloomColor, new Vector3(1, 1, 0)),
+ };
+ drawStacks.Enqueue(new DrawStack(ModAsset.SquareBloom.Value, bars, PrimitiveType.TriangleList));
+ }
+ }
+
+ public virtual void DrawLine_Black(HangingTileAdjustingHelper hangingSystem, Vector2 pos1, Vector2 pos2, float width, ref Queue drawStacks)
+ {
+ if (drawStacks == null)
+ {
+ drawStacks = new Queue();
+ }
+ Vector2 normal = Utils.SafeNormalize(pos1 - pos2, Vector2.zeroVector).RotatedBy(MathHelper.PiOver2) * width / 2f;
+ Color bloomColor = Color.White;
+ float tK = 12f;
+ if (hangingSystem.TimeToKill > 0)
+ {
+ tK = hangingSystem.TimeToKill;
+ }
+ float fade = Math.Min(hangingSystem.Timer, tK) / 12f;
+ bloomColor *= fade;
+ List bars = new List()
+ {
+ new Vertex2D(pos1 + normal, bloomColor, new Vector3(0, 0, 0)),
+ new Vertex2D(pos2 + normal, bloomColor, new Vector3(1, 0, 0)),
+ new Vertex2D(pos1 - normal, bloomColor, new Vector3(0, 1, 0)),
+
+ new Vertex2D(pos1 - normal, bloomColor, new Vector3(0, 1, 0)),
+ new Vertex2D(pos2 + normal, bloomColor, new Vector3(1, 0, 0)),
+ new Vertex2D(pos2 - normal, bloomColor, new Vector3(1, 1, 0)),
+ };
+ drawStacks.Enqueue(new DrawStack(ModAsset.SquareBloom_black.Value, bars, PrimitiveType.TriangleList));
+ }
+
+ public override bool PreDraw(int i, int j, SpriteBatch spriteBatch)
+ {
+ DrawWinch(i, j, spriteBatch);
+ TileFluentDrawManager.AddFluentPoint(this, i, j);
+ return false;
+ }
+
+ public virtual void DrawWinch(int i, int j, SpriteBatch spriteBatch)
+ {
+ Color lightColor = Lighting.GetColor(i, j);
+ var zero = new Vector2(Main.offScreenRange, Main.offScreenRange);
+ if (Main.drawToScreen)
+ {
+ zero = Vector2.Zero;
+ }
+ spriteBatch.Draw(ModAsset.HangingWinch.Value, new Vector2(i, j) * 16 - Main.screenPosition + zero, new Rectangle(0, 0, 16, 16), lightColor, 0, Vector2.zeroVector, 1, SpriteEffects.None, 0);
+ }
+
+ public void FluentDraw(Vector2 screenPosition, Point pos, SpriteBatch spriteBatch, TileDrawing tileDrawing)
+ {
+ Rope rope;
+ RopesOfAllThisTileInTheWorld.TryGetValue(pos, out rope);
+ if (rope != null)
+ {
+ DrawCable(rope, pos, spriteBatch, tileDrawing);
+ if (CanGrasp && !Main.gamePaused)
+ {
+ CheckPlayerGrasp(pos);
+ }
+ }
}
-}
-public class HangingTileUpdate : ModSystem
-{
///
- /// 物å—质点系统
+ /// Paint the hanging chains.
///
- public static MassSpringContainer HangingTileMassSpringSystem = new MassSpringContainer();
- public static EulerSolver HangingTileEulerSolver = new EulerSolver(8);
- public static PBDSolver HangingTilePBDSolver = new PBDSolver(8);
+ ///
+ ///
+ ///
+ ///
+ ///
+ public virtual void DrawCable(Rope rope, Point pos, SpriteBatch spriteBatch, TileDrawing tileDrawing, Color color = default(Color))
+ {
+ // 回声涂料
+ if (!TileDrawing.IsVisible(Main.tile[pos]))
+ {
+ return;
+ }
+
+ var tile = Main.tile[pos];
+ ushort type = tile.TileType;
+ int paint = Main.tile[pos].TileColor;
+ string originalPath = @Texture;
+ string[] pathSegments = originalPath.Split("/");
+ string trimmedTexturePath = Path.Combine(pathSegments.Skip(1).ToArray());
+ Texture2D tex = PaintedTextureSystem.TryGetPaintedTexture(trimmedTexturePath, type, 1, paint, tileDrawing);
+ tex ??= (Texture2D)ModContent.Request(Texture);
+
+ var masses = rope.Masses;
+ for (int i = 0; i < masses.Length; i++)
+ {
+ Mass thisMass = masses[i];
+ int totalPushTime = 80;
+ float pushForcePerFrame = 1.26f;
+ float windCycle = 0;
+ if (tileDrawing.InAPlaceWithWind((int)((thisMass.Position.X - 8) / 16f), (int)((thisMass.Position.Y - 8) / 16f), 1, 1))
+ {
+ windCycle = tileDrawing.GetWindCycle((int)((thisMass.Position.X - 8) / 16f), (int)((thisMass.Position.Y - 8) / 16f), tileDrawing._sunflowerWindCounter);
+ }
+
+ float highestWindGridPushComplex = tileDrawing.GetHighestWindGridPushComplex((int)((thisMass.Position.X - 8) / 16f), (int)((thisMass.Position.Y - 8) / 16f), 1, 1, totalPushTime, pushForcePerFrame, 3, swapLoopDir: true);
+ windCycle += highestWindGridPushComplex;
+ if (!Main.gamePaused)
+ {
+ if (i < masses.Length - 1)
+ {
+ rope.ApplyForceSpecial(i, new Vector2(windCycle / 4.0f, 0.4f * thisMass.Value));
+ }
+ else
+ {
+ rope.ApplyForceSpecial(i, new Vector2(windCycle * 10.0f, 0.4f * thisMass.Value));
+ }
+ }
- public override void PostUpdateEverything()
+ // 支æŒå‘光涂料
+ Color tileLight;
+ if (color != default)
+ {
+ tileLight = color;
+ }
+ else
+ {
+ tileLight = Lighting.GetColor((int)((thisMass.Position.X - 8) / 16f), (int)((thisMass.Position.Y - 8) / 16f));
+ }
+
+ Vector2 toNextMass;
+ if (i < masses.Length - 1)
+ {
+ Mass nextMass = masses[i + 1];
+ toNextMass = nextMass.Position - thisMass.Position;
+ }
+ else
+ {
+ Mass passedMass = masses[i - 1];
+ toNextMass = thisMass.Position - passedMass.Position;
+ }
+ Vector2 drawPos = thisMass.Position - Main.screenPosition;
+ DrawRopeUnit(spriteBatch, tex, drawPos, pos, rope, i, toNextMass.ToRotation() - MathHelper.PiOver2, tileLight);
+ }
+ }
+
+ public void UpdateRopeAdjustment(Rope rope, Point pos)
{
- HangingTileMassSpringSystem = new MassSpringContainer();
- foreach (var HangingTile in TileLoader.tiles.OfType())
+ var masses = rope.Masses;
+ var tile = TileUtils.SafeGetTile(pos);
+ int currentHideUnitCount = MaxCableLength - tile.TileFrameY;
+ if (currentHideUnitCount >= MaxCableLength - 2)
+ {
+ currentHideUnitCount = MaxCableLength - 2;
+ }
+ int oldHideUnitCount = 0;
+ for (int i = 0; i < masses.Length; i++)
{
- foreach (var rope in HangingTile.RopesOfAllThisTileInTheWorld.Values)
+ Mass thisMass = masses[i];
+ if (thisMass.IsStatic)
+ {
+ oldHideUnitCount++;
+ }
+ else
{
- HangingTileMassSpringSystem.AddMassSpringMesh(rope);
+ break;
+ }
+ }
+ for (int i = 0; i < masses.Length; i++)
+ {
+ Mass thisMass = masses[i];
+ if (i <= currentHideUnitCount)
+ {
+ if (i == currentHideUnitCount)
+ {
+ Vector2 stride = pos.ToWorldCoordinates() - thisMass.Position;
+ for (int i2 = i; i2 < masses.Length; i2++)
+ {
+ masses[i2].Position += stride;
+ }
+ }
+ thisMass.IsStatic = true;
+ thisMass.Position = pos.ToWorldCoordinates();
+ continue;
+ }
+ else
+ {
+ thisMass.IsStatic = false;
+ if (i < oldHideUnitCount)
+ {
+ thisMass.Position = pos.ToWorldCoordinates() + new Vector2(0, i - currentHideUnitCount) * UnitLength;
+ }
+ else if (i == oldHideUnitCount)
+ {
+ int deltaUnits = oldHideUnitCount - currentHideUnitCount - 1;
+ Vector2 stride = new Vector2(0, UnitLength * deltaUnits);
+ for (int i2 = i; i2 < masses.Length; i2++)
+ {
+ masses[i2].Position += stride;
+ }
+ }
}
}
- HangingTileEulerSolver.Step(HangingTileMassSpringSystem, 1);
}
- public override void OnWorldLoad()
+ ///
+ /// Custom draw.
+ ///
+ ///
+ ///
+ /// Screen Position
+ ///
+ ///
+ ///
+ public virtual void DrawRopeUnit(SpriteBatch spriteBatch, Texture2D texture, Vector2 drawPos, Point tilePos, Rope rope, int index, float rotation, Color tileLight)
{
- foreach (var HangingTile in TileLoader.tiles.OfType())
+ var masses = rope.Masses;
+ Rectangle frame = new Rectangle(8 * (index % 4), 0, 8, 10);
+ if (index < masses.Length - 1)
{
- HangingTile.RopesOfAllThisTileInTheWorld.Clear();
+ spriteBatch.Draw(texture, drawPos, frame, tileLight, rotation, new Vector2(4f, 0), 1f, SpriteEffects.None, 0);
+ }
+ else
+ {
+ spriteBatch.Draw(texture, drawPos, new Rectangle(0, 12, 32, 40), tileLight, rotation, new Vector2(16f, 0), 1f, SpriteEffects.None, 0);
+ Lighting.AddLight(drawPos + Main.screenPosition, new Vector3(0.8f, 0.8f, 0.2f));
}
- base.OnWorldLoad();
}
- public override void OnWorldUnload()
+ ///
+ /// Try to get the cable entity bound at (, ).
+ ///
+ /// The type to get the entity as
+ /// The tile X-coordinate
+ /// The tile Y-coordinate
+ /// The found instance, if there was one.
+ /// if there was a instance, or if there was no entity present OR the entity was not a instance.
+ public static bool TryGetCableEntityAs(int i, int j, out T entity)
+ where T : TileEntity
{
- foreach (var HangingTile in TileLoader.tiles.OfType())
+ Point16 origin = new Point16(i, j);
+
+ // TileEntity.ByPosition is a Dictionary which contains all placed TileEntity instances in the world
+ // TryGetValue is used to both check if the dictionary has the key, origin, and get the value from that key if it's there
+ if (TileEntity.ByPosition.TryGetValue(origin, out TileEntity existing) && existing is T existingAsT)
{
- HangingTile.RopesOfAllThisTileInTheWorld.Clear();
+ entity = existingAsT;
+ return true;
}
- base.OnWorldUnload();
+
+ entity = null;
+ return false;
}
}
diff --git a/Sources/Everglow.Function/TileHelper/HangingTileAdjustingHelper.cs b/Sources/Everglow.Function/TileHelper/HangingTileAdjustingHelper.cs
new file mode 100644
index 000000000..0f61934d5
--- /dev/null
+++ b/Sources/Everglow.Function/TileHelper/HangingTileAdjustingHelper.cs
@@ -0,0 +1,343 @@
+using Everglow.Commons.Enums;
+using Everglow.Commons.Utilities;
+using Everglow.Commons.Vertex;
+using Everglow.Commons.VFX;
+using Everglow.Commons.VFX.Pipelines;
+using Terraria.Audio;
+using static Everglow.Commons.TileHelper.HangingTile;
+
+namespace Everglow.Commons.TileHelper;
+
+[Pipeline(typeof(WCSPipeline_PointWrap))]
+public class HangingTileAdjustingHelper : Visual
+{
+ public override CodeLayer DrawLayer => CodeLayer.PreDrawFilter;
+
+ public Point FixPoint;
+
+ ///
+ /// 0: mouse over;
+ /// 1: full system.
+ ///
+ public int Style;
+ public int Timer = 0;
+ public int TimeToKill = -1;
+
+ public float StartFrameY60;
+ public float PanelRange = 0;
+ public float HandleRotation;
+
+ public float InitialHandleRotation;
+
+ public Vector2 OldMouseDirection = new Vector2(0, -1);
+ public Queue OldRotatedSpeeds = new Queue();
+
+ ///
+ /// Allow custon drawing styles.
+ ///
+ public delegate void CustomDrawPanel(HangingTileAdjustingHelper hangingAdj, Player player, Color color, ref Queue drawStacks);
+
+ public event CustomDrawPanel CustomPanel;
+
+ public override void OnSpawn()
+ {
+ Player player = Main.LocalPlayer;
+ }
+
+ public override void Update()
+ {
+ Player player = Main.LocalPlayer;
+ int i = FixPoint.X;
+ int j = FixPoint.Y;
+ if (i < 20 || i > Main.maxTilesX - 20 || j < 20 || j > Main.maxTilesY - 20)
+ {
+ Active = false;
+ return;
+ }
+ Tile tile = Main.tile[i, j];
+ HangingTile hangingTile = TileLoader.GetTile(tile.type) as HangingTile;
+ if (hangingTile == null)
+ {
+ Active = false;
+ return;
+ }
+
+ // identify the player.
+ if (hangingTile.WinchAdjustingPlayers.ContainsKey(FixPoint))
+ {
+ Player player2;
+ hangingTile.WinchAdjustingPlayers.TryGetValue(FixPoint, out player2);
+ if (player2 != player)
+ {
+ Active = false;
+ return;
+ }
+ }
+
+ Timer++;
+ if (TimeToKill > 0)
+ {
+ TimeToKill--;
+ if (TimeToKill <= 0)
+ {
+ Kill(hangingTile, player);
+ }
+ }
+
+ if (Timer < 12)
+ {
+ PanelRange = (MathF.Sin(Timer / 10f * MathHelper.Pi - MathHelper.PiOver2) + 1.2f) * 0.5f;
+ }
+ else
+ {
+ PanelRange = 1;
+ }
+ if (TimeToKill < 12 && TimeToKill > 0)
+ {
+ PanelRange *= (MathF.Sin(TimeToKill / 10f * MathHelper.Pi - MathHelper.PiOver2) + 1.2f) * 0.5f;
+ }
+ else
+ {
+ PanelRange *= 1;
+ }
+
+ // åŠ¨æ€æ€§ï¼Œæ ¹æ®åç±»çš„åˆ¤æ–æ¡ä»¶åŽ»æŽ§åˆ¶
+ if (!hangingTile.IsCanRightClick(i, j))
+ {
+ EndAdjustment();
+ return;
+ }
+ if ((player.MouseWorld() - FixPoint.ToWorldCoordinates()).Length() > 400)
+ {
+ EndAdjustment();
+ return;
+ }
+
+ // Only display when mouse over.
+ if (Style == 0)
+ {
+ int x = (int)(player.MouseWorld().X / 16f);
+ int y = (int)(player.MouseWorld().Y / 16f);
+ if (x != FixPoint.X || y != FixPoint.Y)
+ {
+ Active = false;
+ if (hangingTile.MouseOverWinchPlayers.ContainsKey(player))
+ {
+ hangingTile.MouseOverWinchPlayers.Remove(player);
+ }
+ return;
+ }
+ }
+ if (Style == 1)
+ {
+ if (!hangingTile.WinchAdjustingPlayers.ContainsKey(FixPoint))
+ {
+ EndAdjustment();
+ return;
+ }
+ if (!hangingTile.WinchAdjustingPlayers.ContainsKey(FixPoint))
+ {
+ EndAdjustment();
+ return;
+ }
+ float nowFrameY = StartFrameY60 / 60f + (HandleRotation - InitialHandleRotation) * 2;
+ bool endChain = false;
+ if (nowFrameY < 2)
+ {
+ endChain = true;
+ }
+ if (nowFrameY > hangingTile.MaxCableLength - 2)
+ {
+ endChain = true;
+ }
+ if (tile.TileFrameY != (short)Math.Clamp(nowFrameY, 1, hangingTile.MaxCableLength - 1))
+ {
+ if (!endChain)
+ {
+ SoundEngine.PlaySound(SoundID.Unlock.WithVolume(0.5f), FixPoint.ToWorldCoordinates());
+ }
+
+ // æ¯æ¬¡é•¿åº¦å˜åŒ–éƒ½ä¼ å›žHangingTile
+ int oldFrameY = tile.TileFrameY;
+ tile.TileFrameY = (short)Math.Clamp(nowFrameY, 1, hangingTile.MaxCableLength - 1);
+ int deltaLength = tile.TileFrameY - oldFrameY;
+ hangingTile.OnAdjustmentUpdate(FixPoint, player, deltaLength);
+ HangingTileUpdateSystem.WinchAdjustingPlayerTimers[FixPoint] = hangingTile.AdjustingVisualTimeMax;
+ }
+ else
+ {
+ float threthod = hangingTile.AdjustingVisualTimeMax * 0.4f;
+ if (HangingTileUpdateSystem.WinchAdjustingPlayerTimers.ContainsKey(FixPoint) && HangingTileUpdateSystem.WinchAdjustingPlayerTimers[FixPoint] < threthod)
+ {
+ HangingTileUpdateSystem.WinchAdjustingPlayerTimers[FixPoint] = threthod;
+ }
+ }
+
+ Vector2 handleDir = new Vector2(1, 0).RotatedBy(HandleRotation);
+ Vector2 newDir = Utils.SafeNormalize(FixPoint.ToWorldCoordinates() - player.MouseWorld(), new Vector2(0, -1));
+ float addAccRot = MathF.Asin(-Vector3.Cross(new Vector3(newDir, 0), new Vector3(handleDir, 0)).Z);
+ float addOldToNewRot = MathF.Asin(-Vector3.Cross(new Vector3(newDir, 0), new Vector3(OldMouseDirection, 0)).Z);
+ OldMouseDirection = newDir;
+ OldRotatedSpeeds.Enqueue(addOldToNewRot);
+ if (OldRotatedSpeeds.Count > 3)
+ {
+ OldRotatedSpeeds.Dequeue();
+ }
+ float cosValue = Vector2.Dot(handleDir, newDir);
+ if (nowFrameY >= 1 && nowFrameY <= hangingTile.MaxCableLength - 1)
+ {
+ HandleRotation += addAccRot;
+ }
+ else if (nowFrameY < 1 && RotatedClockwise() && cosValue > 0.8f)
+ {
+ HandleRotation += addAccRot;
+ }
+ else if (nowFrameY > hangingTile.MaxCableLength - 1 && RotatedCounterclockwise() && cosValue > 0.8f)
+ {
+ HandleRotation += addAccRot;
+ }
+ int x = (int)(player.MouseWorld().X / 16f);
+ int y = (int)(player.MouseWorld().Y / 16f);
+ if (Main.mouseRight && Main.mouseRightRelease && (x != FixPoint.X || y != FixPoint.Y))
+ {
+ EndAdjustment();
+ return;
+ }
+ }
+ base.Update();
+ }
+
+ public bool RotatedClockwise()
+ {
+ for (int i = 0; i < OldRotatedSpeeds.Count; i++)
+ {
+ if (OldRotatedSpeeds.ToArray()[i] <= 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public bool RotatedCounterclockwise()
+ {
+ for (int i = 0; i < OldRotatedSpeeds.Count; i++)
+ {
+ if (OldRotatedSpeeds.ToArray()[i] >= 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public void EndAdjustment()
+ {
+ if (TimeToKill < 0)
+ {
+ TimeToKill = 12;
+ }
+ }
+
+ public void Kill(HangingTile hangingTile, Player owner)
+ {
+ Active = false;
+ if (hangingTile.MouseOverWinchPlayers.ContainsKey(owner))
+ {
+ hangingTile.MouseOverWinchPlayers.Remove(owner);
+ }
+ if (hangingTile.WinchAdjustingPlayers.ContainsKey(FixPoint))
+ {
+ hangingTile.WinchAdjustingPlayers.Remove(FixPoint);
+ }
+ hangingTile.OnAdjustmentEnd(FixPoint, owner);
+ }
+
+ public override void Draw()
+ {
+ int i = FixPoint.X;
+ int j = FixPoint.Y;
+ if (i < 20 || i > Main.maxTilesX - 20)
+ {
+ if (j < 20 || j > Main.maxTilesY - 20)
+ {
+ Active = false;
+ return;
+ }
+ }
+ Player player = Main.LocalPlayer;
+ Tile tile = Main.tile[i, j];
+ HangingTile hangingTile = TileLoader.GetTile(tile.type) as HangingTile;
+ if (hangingTile == null)
+ {
+ Active = false;
+ return;
+ }
+ Color drawColor = Color.Lerp(new Color(0.75f, 0.75f, 1f, 0.5f), new Color(0.85f, 0.85f, 0.75f, 0.5f), MathF.Sin((float)Main.timeForVisualEffects * 0.08f) * 0.5f + 0.5f);
+ Color origDrawColor = drawColor;
+ if (Style == 1)
+ {
+ float nowFrameY = StartFrameY60 / 60f + HandleRotation * 2;
+ if (nowFrameY < 5)
+ {
+ drawColor = Color.Lerp(drawColor, new Color(1f, 0f, 0f, 0.8f), (5 - nowFrameY) / 4f);
+ }
+ if (nowFrameY > hangingTile.MaxCableLength - 5)
+ {
+ drawColor = Color.Lerp(drawColor, new Color(1f, 0f, 0f, 0.8f), (nowFrameY - (hangingTile.MaxCableLength - 5)) / 4f);
+ }
+ }
+
+ // If your HeldItem doesn't match with the tile type, it turns red.
+ if (!hangingTile.IsCanRightClick(i, j))
+ {
+ drawColor = new Color(1f, 0, 0, 0.5f);
+ Main.instance.MouseText("Different Type Error", ItemRarityID.Red);
+ }
+
+ // The circle panel
+ Vector2 rotCenter = FixPoint.ToWorldCoordinates();
+ Vector2 cut = new Vector2(1, 0).RotatedBy(HandleRotation + MathHelper.Pi);
+ if (hangingTile.RopesOfAllThisTileInTheWorld.ContainsKey(FixPoint))
+ {
+ if (Style == 1)
+ {
+ Queue drawStacks = new Queue();
+ CustomPanel?.Invoke(this, player, origDrawColor, ref drawStacks);
+ while (drawStacks.Count > 0)
+ {
+ DrawStack currentDS = drawStacks.Dequeue();
+ Ins.Batch.Draw(currentDS.Texture, currentDS.Vertices, currentDS.PType);
+ }
+ }
+ }
+ DrawBlockBound(FixPoint.X, FixPoint.Y, drawColor, HandleRotation);
+ }
+
+ public void DrawBlockBound(int i, int j, Color color, float rotation)
+ {
+ Vector2 pos = new Vector2(i, j) * 16 + new Vector2(8);
+ List bars = new List()
+ {
+ new Vertex2D(pos + new Vector2(-8, -8).RotatedBy(rotation), color, new Vector3(0, 0, 0)),
+ new Vertex2D(pos + new Vector2(8, -8).RotatedBy(rotation), color, new Vector3(1, 0, 0)),
+ new Vertex2D(pos + new Vector2(-8, 8).RotatedBy(rotation), color, new Vector3(0, 1, 0)),
+
+ new Vertex2D(pos + new Vector2(-8, 8).RotatedBy(rotation), color, new Vector3(0, 1, 0)),
+ new Vertex2D(pos + new Vector2(8, -8).RotatedBy(rotation), color, new Vector3(1, 0, 0)),
+ new Vertex2D(pos + new Vector2(8, 8).RotatedBy(rotation), color, new Vector3(1, 1, 0)),
+ };
+ Ins.Batch.Draw(ModAsset.TileBlock.Value, bars, PrimitiveType.TriangleList);
+ }
+
+ public void RegisterCustomPanelDrawing(CustomDrawPanel customDrawing)
+ {
+ CustomPanel += customDrawing;
+ }
+
+ ///
+ public void UnregisterCustomPanelDrawing(CustomDrawPanel customDrawing)
+ {
+ CustomPanel -= customDrawing;
+ }
+}
diff --git a/Sources/Everglow.Function/TileHelper/HangingTilePlayer.cs b/Sources/Everglow.Function/TileHelper/HangingTilePlayer.cs
new file mode 100644
index 000000000..f57901bbc
--- /dev/null
+++ b/Sources/Everglow.Function/TileHelper/HangingTilePlayer.cs
@@ -0,0 +1,78 @@
+namespace Everglow.Commons.TileHelper;
+
+public class HangingTile_Player : ModPlayer
+{
+ public int SwitchVineCoolTimer = 0;
+
+ public bool Grasping = false;
+
+ public Vector2 OldGraspPos = default;
+
+ public override void PostUpdate()
+ {
+ if (SwitchVineCoolTimer > 0)
+ {
+ SwitchVineCoolTimer--;
+ }
+ else
+ {
+ SwitchVineCoolTimer = 0;
+ }
+ GraspHangingTile();
+ PreventMapFalling();
+ if (Grasping)
+ {
+ OldGraspPos = Player.Center;
+ }
+ base.PostUpdate();
+ }
+
+ public void PreventMapFalling()
+ {
+ if (Main.mapFullscreen && Grasping)
+ {
+ if (OldGraspPos != default)
+ {
+ Player.Center = OldGraspPos;
+ }
+ }
+ }
+
+ ///
+ /// 抓ä½hanging绳索,当玩家抓时,é历hanging䏿‰€æœ‰ç»³ç´¢çš„点,去抓ä½é‚£ä¸ªæ»¡è¶³èŒƒå›´å†…的绳索,
+ /// å‰ææ˜¯å®ƒå½“å‰ä¸åœ¨è°ƒæ•´çжæ€
+ ///
+ public void GraspHangingTile()
+ {
+ if (!Player.mount.Active && Player.controlUp && !HangingTile.RopeGraspingPlayer.ContainsValue(Player))
+ {
+ foreach (var hangingTile in TileLoader.tiles.OfType())
+ {
+ if (hangingTile.CanGrasp)
+ {
+ foreach (var point in hangingTile.RopesOfAllThisTileInTheWorld.Keys)
+ {
+ // 点在调整ä¸èƒ½æŠ“
+ if (hangingTile.WinchAdjustingPlayers.ContainsKey(point))
+ {
+ continue;
+ }
+ var rope = hangingTile.RopesOfAllThisTileInTheWorld[point];
+ Vector2 tipPos = rope.Masses.Last().Position;
+ if (Vector2.Distance(Player.Center, tipPos) <= hangingTile.GraspDetectRange)
+ {
+ Point targetPoint = hangingTile.RopesOfAllThisTileInTheWorld.FirstOrDefault(kv => kv.Value == rope).Key;
+ hangingTile.AddPlayerToRope(Player, rope, targetPoint);
+ Grasping = true;
+ break;
+ }
+ }
+ if (HangingTile.RopeGraspingPlayer.ContainsValue(Player))
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Sources/Everglow.Function/TileHelper/HangingTileUpdateSystem.cs b/Sources/Everglow.Function/TileHelper/HangingTileUpdateSystem.cs
new file mode 100644
index 000000000..c22992fcf
--- /dev/null
+++ b/Sources/Everglow.Function/TileHelper/HangingTileUpdateSystem.cs
@@ -0,0 +1,60 @@
+using Everglow.Commons.Physics.MassSpringSystem;
+
+namespace Everglow.Commons.TileHelper;
+
+///
+/// A ModSystem that manages the update of hanging tiles in the world. It handles the physics simulation of hanging tiles using a mass-spring system and updates their positions accordingly. This system is responsible for ensuring that hanging tiles behave realistically when interacted with or affected by external forces.
+///
+public class HangingTileUpdateSystem : ModSystem
+{
+ public static MassSpringContainer HangingTileMassSpringSystem = new MassSpringContainer();
+ public static EulerSolver HangingTileEulerSolver = new EulerSolver(8);
+ public static PBDSolver HangingTilePBDSolver = new PBDSolver(8);
+
+ public static Dictionary WinchAdjustingPlayerTimers = new Dictionary();
+
+ public override void PostUpdateEverything()
+ {
+ HangingTileMassSpringSystem = new MassSpringContainer();
+ foreach (var HangingTile in TileLoader.tiles.OfType())
+ {
+ foreach (var rope in HangingTile.RopesOfAllThisTileInTheWorld.Values)
+ {
+ HangingTileMassSpringSystem.AddMassSpringMesh(rope);
+ }
+ }
+ HangingTileEulerSolver.Step(HangingTileMassSpringSystem, 1);
+ foreach(var k in WinchAdjustingPlayerTimers.Keys.ToList())
+ {
+ WinchAdjustingPlayerTimers[k] -= 1;
+ if (WinchAdjustingPlayerTimers[k] <= 0)
+ {
+ WinchAdjustingPlayerTimers.Remove(k);
+ }
+ }
+ }
+
+ public override void OnWorldLoad()
+ {
+ foreach (var hangingTile in TileLoader.tiles.OfType())
+ {
+ hangingTile.RopesOfAllThisTileInTheWorld.Clear();
+ hangingTile.WinchAdjustingPlayers.Clear();
+ hangingTile.MouseOverWinchPlayers.Clear();
+ }
+ HangingTile.RopeGraspingPlayer.Clear();
+ base.OnWorldLoad();
+ }
+
+ public override void OnWorldUnload()
+ {
+ foreach (var hangingTile in TileLoader.tiles.OfType())
+ {
+ hangingTile.RopesOfAllThisTileInTheWorld.Clear();
+ hangingTile.WinchAdjustingPlayers.Clear();
+ hangingTile.MouseOverWinchPlayers.Clear();
+ }
+ HangingTile.RopeGraspingPlayer.Clear();
+ base.OnWorldUnload();
+ }
+}
diff --git a/Sources/Everglow.Function/TileHelper/ITileFluentlyDrawn.cs b/Sources/Everglow.Function/TileHelper/ITileFluentlyDrawn.cs
index f1cc59001..7872c982f 100644
--- a/Sources/Everglow.Function/TileHelper/ITileFluentlyDrawn.cs
+++ b/Sources/Everglow.Function/TileHelper/ITileFluentlyDrawn.cs
@@ -18,6 +18,7 @@ public interface ITileFluentlyDrawn
/// 工具类,风速和摇晃有关的都得é 它
void FluentDraw(Vector2 screenPosition, Point pos, SpriteBatch spriteBatch, TileDrawing tileDrawing);
}
+
public struct BasicDrawInfo
{
public Vector2 DrawCenterPos;
diff --git a/Sources/Everglow.Function/TileHelper/ITileOffsetOverScreenDrawn.cs b/Sources/Everglow.Function/TileHelper/ITileOffsetOverScreenDrawn.cs
new file mode 100644
index 000000000..8cd14bf61
--- /dev/null
+++ b/Sources/Everglow.Function/TileHelper/ITileOffsetOverScreenDrawn.cs
@@ -0,0 +1,8 @@
+namespace Everglow.Commons.TileHelper;
+
+public interface ITileOffsetOverScreenDrawn
+{
+ public static List SpecialTilePositon = new List();
+
+ public int TileOffsetScreenRange();
+}
diff --git a/Sources/Everglow.Function/TileHelper/ShapeDataTile.cs b/Sources/Everglow.Function/TileHelper/ShapeDataTile.cs
index 3c5ac5201..a26683ebf 100644
--- a/Sources/Everglow.Function/TileHelper/ShapeDataTile.cs
+++ b/Sources/Everglow.Function/TileHelper/ShapeDataTile.cs
@@ -28,6 +28,11 @@ public override void SetStaticDefaults()
}
public int[,] PixelHasTile;
+
+ ///
+ /// If top, bottom, left or right is not , it must be solid tile for valid placement.
+ ///
+ public int[,] PixelHasAttach;
public int TotalWidth;
public int TotalHeight;
@@ -52,6 +57,7 @@ public override void Load()
imageData.ProcessPixelRows(accessor =>
{
PixelHasTile = new int[accessor.Width, accessor.Height];
+ PixelHasAttach = new int[accessor.Width, accessor.Height];
TotalWidth = accessor.Width;
TotalHeight = accessor.Height;
for (int y = 0; y < accessor.Height; y++)
@@ -61,6 +67,7 @@ public override void Load()
{
ref var pixel = ref pixelRow[x];
PixelHasTile[x, y] = pixel.R;
+ PixelHasAttach[x, y] |= pixel.G;
}
}
});
@@ -122,6 +129,15 @@ public virtual void CustomDropItem(int i, int j)
}
}
+ ///
+ /// ä»Žå·¦ä¸Šè§’å®‰ç½®ä¸€ä¸ªé€ åž‹ç‰©å—
+ ///
+ ///
+ public virtual void PlaceOriginAtTopLeft(Point pos)
+ {
+ PlaceOriginAtTopLeft(pos.X, pos.Y);
+ }
+
///
/// ä»Žå·¦ä¸Šè§’å®‰ç½®ä¸€ä¸ªé€ åž‹ç‰©å—
///
@@ -150,6 +166,15 @@ public virtual void PlaceOriginAtTopLeft(int x, int y)
}
}
+ ///
+ /// ä»Žå·¦ä¸‹è§’å®‰ç½®ä¸€ä¸ªé€ åž‹ç‰©å—
+ ///
+ ///
+ public virtual void PlaceOriginAtBottomLeft(Point pos)
+ {
+ PlaceOriginAtBottomLeft(pos.X, pos.Y);
+ }
+
///
/// ä»Žå·¦ä¸‹è§’å®‰ç½®ä¸€ä¸ªé€ åž‹ç‰©å—
///
@@ -178,6 +203,32 @@ public virtual void PlaceOriginAtBottomLeft(int x, int y)
}
}
+ public virtual void PlaceAtTileObjectDataOrigin(int i, int j)
+ {
+ TileObjectData tileObjectData = TileObjectData.GetTileData(Type, Main.LocalPlayer.HeldItem.placeStyle);
+ i -= tileObjectData.Origin.X;
+ j -= tileObjectData.Origin.Y;
+ if (i + TotalWidth > Main.maxTilesX || i < 0 || j + TotalHeight > Main.maxTilesY || j < 0)
+ {
+ return;
+ }
+ for (int x = 0; x < TotalWidth; x++)
+ {
+ for (int y = 0; y < TotalHeight; y++)
+ {
+ if (PixelHasTile[x, y] >= 200)
+ {
+ Tile tile = Main.tile[x + i, y + j];
+ tile.TileType = Type;
+ tile.TileFrameX = (short)(x * 18);
+ tile.TileFrameY = (short)(y * 18);
+ tile.HasTile = true;
+ }
+ }
+ }
+ NetMessage.SendTileSquare(-1, i, j, TotalWidth, TotalHeight);
+ }
+
///
/// 判定底部平å¦ä»¥åŠèƒ½å¦å®¹çº³ä¸‹å¼‚å½¢å—
///
@@ -200,36 +251,14 @@ public bool CanPlaceAtBottomLeft(int x, int y)
Tile tile = Main.tile[x + i, y - j];
if (tile.HasTile)
{
- bool fragile = false;
- if (Main.tileCut[tile.TileType])
- {
- fragile = true;
- }
- if (Main.tilePile[tile.TileType])
- {
- fragile = true;
- }
- if (!fragile)
+ if (!TileFragile(tile))
{
return false;
}
}
if (j == 0)
{
- Tile tileBottom = Main.tile[x + i, y + 1];
- if (!tileBottom.HasTile)
- {
- return false;
- }
- if (tileBottom.Slope != SlopeType.Solid)
- {
- return false;
- }
- if (tileBottom.IsHalfBlock)
- {
- return false;
- }
- if (!(Main.tileSolidTop[tileBottom.TileType] || Main.tileSolid[tileBottom.TileType]))
+ if (!TileSolidWithNoSlope(x + i, y + 1))
{
return false;
}
@@ -262,36 +291,60 @@ public bool CanPlaceAtTopLeft(int x, int y)
Tile tile = Main.tile[x + i, y + j];
if (tile.HasTile)
{
- bool fragile = false;
- if (Main.tileCut[tile.TileType])
- {
- fragile = true;
- }
- if (Main.tilePile[tile.TileType])
- {
- fragile = true;
- }
- if (!fragile)
+ if (!TileFragile(tile))
{
return false;
}
}
if (j == 0)
{
- Tile tileTop = Main.tile[x + i, y - 1];
- if (!tileTop.HasTile)
+ if (!TileSolidWithNoSlope(x + i, y - 1))
{
return false;
}
- if (tileTop.Slope != SlopeType.Solid)
- {
- return false;
- }
- if (tileTop.IsHalfBlock)
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ ///
+ /// Check collision when place the tile.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public bool NoCollideInSolidGrid(int i, int j, bool checkAttach = true)
+ {
+ if (Main.dedServ)
+ {
+ return false;
+ }
+ TileObjectData tileObjectData = TileObjectData.GetTileData(Type, Main.LocalPlayer.HeldItem.placeStyle);
+ i -= tileObjectData.Origin.X;
+ j -= tileObjectData.Origin.Y;
+ for (int x = 0; x < TotalWidth; x++)
+ {
+ for (int y = 0; y < TotalHeight; y++)
+ {
+ if (PixelHasTile[x, y] >= 200)
+ {
+ var tile = TileUtils.SafeGetTile(i + x, j + y);
+ if (tile.HasTile)
+ {
+ if (!TileFragile(tile))
{
return false;
}
- if (!(Main.tileSolidTop[tileTop.TileType] || Main.tileSolid[tileTop.TileType]))
+ }
+ }
+ if (checkAttach)
+ {
+ if (PixelHasAttach[x, y] > 200)
+ {
+ if (!ValidAttachCheck(i, j, x, y))
{
return false;
}
@@ -301,4 +354,65 @@ public bool CanPlaceAtTopLeft(int x, int y)
}
return true;
}
+
+ public bool ValidAttachCheck(int i, int j, int x, int y)
+ {
+ if (!TileSolidWithNoSlope(i + x + 1, j + y) && PixelHasTile[x + 1, y] < 200)
+ {
+ return false;
+ }
+ if (!TileSolidWithNoSlope(i + x, j + y + 1) && PixelHasTile[x, y + 1] < 200)
+ {
+ return false;
+ }
+ if (!TileSolidWithNoSlope(i + x - 1, j + y) && PixelHasTile[x - 1, y] < 200)
+ {
+ return false;
+ }
+ if (!TileSolidWithNoSlope(i + x, j + y - 1) && PixelHasTile[x, y - 1] < 200)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public bool TileFragile(Tile tile)
+ {
+ bool fragile = false;
+ if (Main.tileCut[tile.TileType])
+ {
+ fragile = true;
+ }
+ if (Main.tilePile[tile.TileType])
+ {
+ fragile = true;
+ }
+ return fragile;
+ }
+
+ public bool TileSolidWithNoSlope(int i, int j)
+ {
+ return TileSolidWithNoSlope(TileUtils.SafeGetTile(i, j));
+ }
+
+ public bool TileSolidWithNoSlope(Tile tile)
+ {
+ if (!tile.HasTile)
+ {
+ return false;
+ }
+ if (tile.Slope != SlopeType.Solid)
+ {
+ return false;
+ }
+ if (tile.IsHalfBlock)
+ {
+ return false;
+ }
+ if (!(Main.tileSolidTop[tile.TileType] || Main.tileSolid[tile.TileType]))
+ {
+ return false;
+ }
+ return true;
+ }
}
diff --git a/Sources/Everglow.Function/UI/EverglowUISystem.cs b/Sources/Everglow.Function/UI/EverglowUISystem.cs
index eca076977..8982813b0 100644
--- a/Sources/Everglow.Function/UI/EverglowUISystem.cs
+++ b/Sources/Everglow.Function/UI/EverglowUISystem.cs
@@ -73,7 +73,7 @@ public EverglowUISystem()
///
public void Load()
{
- var containers = from c in GetType().Assembly.GetTypes()
+ var containers = from c in Ins.ModuleManager.Types
where !c.IsAbstract && c.IsSubclassOf(typeof(UIContainerElement))
select c;
UIContainerElement element;
diff --git a/Sources/Everglow.Function/UI/UIElements/UIItemSlot.cs b/Sources/Everglow.Function/UI/UIElements/UIItemSlot.cs
index 2890a8cb7..864da5281 100644
--- a/Sources/Everglow.Function/UI/UIElements/UIItemSlot.cs
+++ b/Sources/Everglow.Function/UI/UIElements/UIItemSlot.cs
@@ -1,5 +1,6 @@
using ReLogic.Graphics;
using Terraria.GameContent;
+using Terraria.UI;
namespace Everglow.Commons.UI.UIElements
{
@@ -69,7 +70,13 @@ public class UIItemSlot : BaseElement
///
public float Opacity { get; set; }
- public UIItemSlot(Texture2D texture = default(Texture2D)) : base()
+ ///
+ /// 是å¦ä¸ºå•†åº—ç‰©å“æ§½, åªè¦æ»¡è¶³æ¡ä»¶, å…è®¸æ— ç©·å–出
+ ///
+ public bool ShopSlot { get; set; } = false;
+
+ public UIItemSlot(Texture2D texture = default(Texture2D))
+ : base()
{
Opacity = 1f;
ContainedItem = new Item();
@@ -77,7 +84,7 @@ public class UIItemSlot : BaseElement
SlotBackTexture = texture == default(Texture2D) ? TextureAssets.InventoryBack.Value : texture;
DrawColor = Color.White;
CornerSize = new Vector2(10, 10);
- Tooltip = "";
+ Tooltip = string.Empty;
Info.Width.SetValue(50f, 0f);
Info.Height.SetValue(50f, 0f);
}
@@ -87,96 +94,110 @@ public override void LoadEvents()
base.LoadEvents();
Events.OnLeftClick += element =>
{
- //å¼€å¯èƒŒåŒ…
- //Main.playerInventory = true;
+ // å¼€å¯èƒŒåŒ…
+ // Main.playerInventory = true;
- //å½“é¼ æ ‡æ²¡ç‰©å“,框里有物å“的时候
- if (Main.mouseItem.type == ItemID.None && ContainedItem != null && ContainedItem.type != ItemID.None)
+ // å½“é¼ æ ‡æ²¡ç‰©å“,框里有物å“的时候
+ if (Main.mouseItem.IsAir && ContainedItem != null && ContainedItem.type != ItemID.None)
{
- //如果å¯ä»¥æ‹¿èµ·ç‰©å“
+ // 如果å¯ä»¥æ‹¿èµ·ç‰©å“
if (CanTakeOutSlot == null || CanTakeOutSlot(ContainedItem))
{
- //拿出物å“
+ // 拿出物å“
Main.mouseItem = ContainedItem.Clone();
- ContainedItem = new Item();
- ContainedItem.SetDefaults(0, true);
+ if (!ItemID.Sets.Deprecated[ContainedItem.type])
+ {
+ Main.mouseItem.SetDefaults(ContainedItem.type);
+ Main.mouseItem.stack = ContainedItem.stack;
+ }
+ if (!ShopSlot)
+ {
+ ContainedItem = new Item();
+ ContainedItem.SetDefaults(ItemID.None, true);
+ }
- //调用委托
+ // 调用委托
OnPickItem?.Invoke(this);
- //è§¦å‘æ”¾ç‰©å“声音
- //SoundEngine.PlaySound(7, -1, -1, 1, 1f, 0.0f);
+ // è§¦å‘æ”¾ç‰©å“声音
+ // SoundEngine.PlaySound(7, -1, -1, 1, 1f, 0.0f);
}
}
- //å½“é¼ æ ‡æœ‰ç‰©å“,框里没物å“的时候
+
+ // å½“é¼ æ ‡æœ‰ç‰©å“,框里没物å“的时候
else if (Main.mouseItem.type != ItemID.None && (ContainedItem == null || ContainedItem.type == ItemID.None))
{
- //如果å¯ä»¥æ”¾å…¥ç‰©å“
+ // 如果å¯ä»¥æ”¾å…¥ç‰©å“
if (CanPutInSlot == null || CanPutInSlot(Main.mouseItem))
{
- //放入物å“
+ // 放入物å“
ContainedItem = Main.mouseItem.Clone();
Main.mouseItem = new Item();
- Main.mouseItem.SetDefaults(0, true);
+ Main.mouseItem.SetDefaults(ItemID.None, true);
- //调用委托
+ // 调用委托
OnPutItem?.Invoke(this);
- //è§¦å‘æ”¾ç‰©å“声音
- //SoundEngine.PlaySound(7, -1, -1, 1, 1f, 0.0f);
+ // è§¦å‘æ”¾ç‰©å“声音
+ // SoundEngine.PlaySound(7, -1, -1, 1, 1f, 0.0f);
}
}
- //å½“é¼ æ ‡å’Œæ¡†éƒ½æœ‰ç‰©å“æ—¶
+
+ // å½“é¼ æ ‡å’Œæ¡†éƒ½æœ‰ç‰©å“æ—¶
else if (Main.mouseItem.type != ItemID.None && ContainedItem != null && ContainedItem.type != ItemID.None)
{
- //如果ä¸èƒ½æ”¾å…¥ç‰©å“
+ // 如果ä¸èƒ½æ”¾å…¥ç‰©å“
if (!(CanPutInSlot == null || CanPutInSlot(Main.mouseItem)))
{
- //䏿–函数
+ // 䏿–函数
return;
}
- //如果框里的物å“å’Œé¼ æ ‡çš„ç›¸åŒ
+ // 如果框里的物å“å’Œé¼ æ ‡çš„ç›¸åŒ
if (Main.mouseItem.type == ContainedItem.type)
{
- //æ¡†é‡Œçš„ç‰©å“æ•°é‡åŠ ä¸Šé¼ æ ‡ç‰©å“æ•°é‡
+ // æ¡†é‡Œçš„ç‰©å“æ•°é‡åŠ ä¸Šé¼ æ ‡ç‰©å“æ•°é‡
ContainedItem.stack += Main.mouseItem.stack;
- //å¦‚æžœæ¡†é‡Œç‰©å“æ•°é‡å¤§äºŽæ•°é‡ä¸Šé™
+
+ // å¦‚æžœæ¡†é‡Œç‰©å“æ•°é‡å¤§äºŽæ•°é‡ä¸Šé™
if (ContainedItem.stack > ContainedItem.maxStack)
{
- //è®¡ç®—é¼ æ ‡ç‰©å“æ•°é‡ï¼Œå¹¶å°†æ¡†å†…ç‰©å“æ•°é‡ä¿®æ”¹ä¸ºæ•°é‡ä¸Šé™
+ // è®¡ç®—é¼ æ ‡ç‰©å“æ•°é‡ï¼Œå¹¶å°†æ¡†å†…ç‰©å“æ•°é‡ä¿®æ”¹ä¸ºæ•°é‡ä¸Šé™
var exceed = ContainedItem.stack - ContainedItem.maxStack;
ContainedItem.stack = ContainedItem.maxStack;
Main.mouseItem.stack = exceed;
}
- //å之
+
+ // å之
else
{
- //æ¸…ç©ºé¼ æ ‡ç‰©å“
+ // æ¸…ç©ºé¼ æ ‡ç‰©å“
Main.mouseItem = new Item();
}
}
- //如果å¯ä»¥æ”¾å…¥ç‰©å“也能拿出物å“
+
+ // 如果å¯ä»¥æ”¾å…¥ç‰©å“也能拿出物å“
else if ((CanPutInSlot == null || CanPutInSlot(Main.mouseItem))
&& (CanTakeOutSlot == null || CanTakeOutSlot(ContainedItem)))
{
- //äº¤æ¢æ¡†å†…物å“å’Œé¼ æ ‡ç‰©å“
+ // äº¤æ¢æ¡†å†…物å“å’Œé¼ æ ‡ç‰©å“
var tmp = Main.mouseItem.Clone();
Main.mouseItem = ContainedItem;
ContainedItem = tmp;
}
- //è§¦å‘æ”¾ç‰©å“声音
- //SoundEngine.PlaySound(7, -1, -1, 1, 1f, 0.0f);
+ // è§¦å‘æ”¾ç‰©å“声音
+ // SoundEngine.PlaySound(7, -1, -1, 1, 1f, 0.0f);
}
- //å之
+
+ // å之
else
{
- //䏿–函数
+ // 䏿–函数
return;
}
- //调用委托
+ // 调用委托
PostExchangeItem?.Invoke(this);
};
}
@@ -193,31 +214,27 @@ protected override void DrawSelf(SpriteBatch sb)
float scale = Info.Size.X / 50f;
DynamicSpriteFont font = FontAssets.MouseText.Value;
- //调用原版的介ç»ç»˜åˆ¶
+
+ // 调用原版的介ç»ç»˜åˆ¶
if (ContainedItem != null && ContainsPoint(Main.MouseScreen) && ContainedItem.type != ItemID.None)
{
Main.hoverItemName = ContainedItem.Name;
Main.HoverItem = ContainedItem.Clone();
}
- //获å–当å‰UI部件的信æ¯
+
+ // 获å–当å‰UI部件的信æ¯
var DrawRectangle = Info.TotalHitBox;
- //ç»˜åˆ¶ç‰©å“æ¡†
- DrawAdvBox(sb, (int)DrawRectangle.X, (int)DrawRectangle.Y,
- (int)DrawRectangle.Width, (int)DrawRectangle.Height,
+
+ // ç»˜åˆ¶ç‰©å“æ¡†
+ DrawAdvBox(sb, DrawRectangle.X, DrawRectangle.Y,
+ DrawRectangle.Width, DrawRectangle.Height,
DrawColor * Opacity, SlotBackTexture, CornerSize, 1f);
if (ContainedItem != null && ContainedItem.type != ItemID.None)
{
var frame = Main.itemAnimations[ContainedItem.type] != null ? Main.itemAnimations[ContainedItem.type].GetFrame(TextureAssets.Item[ContainedItem.type].Value) : Item.GetDrawHitbox(ContainedItem.type, null);
- //绘制物å“贴图
- sb.Draw(TextureAssets.Item[ContainedItem.type].Value, new Vector2(DrawRectangle.X + DrawRectangle.Width / 2,
- DrawRectangle.Y + DrawRectangle.Height / 2) - (new Vector2(frame.Width, frame.Height) / 2f * scale),
- new Rectangle?(frame), Color.White * Opacity, 0f, Vector2.Zero, scale, 0, 0);
-
- //绘制物å“左下角那个代表数é‡çš„æ•°å—
- if (ContainedItem.stack > 1)
- {
- sb.DrawString(font, ContainedItem.stack.ToString(), new Vector2(DrawRectangle.X + 10, DrawRectangle.Y + DrawRectangle.Height - 20), Color.White * Opacity, 0f, Vector2.Zero, scale * 0.8f, SpriteEffects.None, 0f);
- }
+ Main.inventoryScale = 36 / 52f * Info.TotalHitBox.Width / 36f;
+ Item t_item = ContainedItem;
+ ItemSlot.Draw(sb, ref t_item, 21, new Vector2(DrawRectangle.X, DrawRectangle.Y));
}
}
@@ -254,13 +271,13 @@ public void DrawAdvBox(SpriteBatch sp, int x, int y, int w, int h, Color c, Text
}
sp.Draw(box, new Rectangle(x, y, width, height), new Rectangle(0, 0, width, height), c);
sp.Draw(box, new Rectangle(x + width, y, w - width * 2, height), new Rectangle(width, 0, box.Width - width * 2, height), c);
- sp.Draw(box, new Rectangle((x + w) - width, y, width, height), new Rectangle(box.Width - width, 0, width, height), c);
+ sp.Draw(box, new Rectangle(x + w - width, y, width, height), new Rectangle(box.Width - width, 0, width, height), c);
sp.Draw(box, new Rectangle(x, y + height, width, h - height * 2), new Rectangle(0, height, width, box.Height - height * 2), c);
sp.Draw(box, new Rectangle(x + width, y + height, w - width * 2, h - height * 2), new Rectangle(width, height, box.Width - width * 2, box.Height - height * 2), c);
- sp.Draw(box, new Rectangle((x + w) - width, y + height, width, h - height * 2), new Rectangle(box.Width - width, height, width, box.Height - height * 2), c);
- sp.Draw(box, new Rectangle(x, (y + h) - height, width, height), new Rectangle(0, box.Height - height, width, height), c);
- sp.Draw(box, new Rectangle(x + width, (y + h) - height, w - width * 2, height), new Rectangle(width, box.Height - height, box.Width - width * 2, height), c);
- sp.Draw(box, new Rectangle((x + w) - width, (y + h) - height, width, height), new Rectangle(box.Width - width, box.Height - height, width, height), c);
+ sp.Draw(box, new Rectangle(x + w - width, y + height, width, h - height * 2), new Rectangle(box.Width - width, height, width, box.Height - height * 2), c);
+ sp.Draw(box, new Rectangle(x, y + h - height, width, height), new Rectangle(0, box.Height - height, width, height), c);
+ sp.Draw(box, new Rectangle(x + width, y + h - height, w - width * 2, height), new Rectangle(width, box.Height - height, box.Width - width * 2, height), c);
+ sp.Draw(box, new Rectangle(x + w - width, y + h - height, width, height), new Rectangle(box.Width - width, box.Height - height, width, height), c);
}
}
}
diff --git a/Sources/Everglow.Function/UI/UISystem.cs b/Sources/Everglow.Function/UI/UISystem.cs
index 9342a31f7..4a7ce4318 100644
--- a/Sources/Everglow.Function/UI/UISystem.cs
+++ b/Sources/Everglow.Function/UI/UISystem.cs
@@ -1,12 +1,15 @@
using Everglow.Commons.DataStructures;
using Everglow.Commons.Enums;
using Everglow.Commons.Utilities;
+using MonoMod.Cil;
using Terraria.UI;
namespace Everglow.Commons.UI
{
public class UISystem : ModSystem
{
+ private const int SpecialShopWhoAmI_Zero = 65536;
+
public static EverglowUISystem EverglowUISystem
{
get => Instance.system;
@@ -26,6 +29,23 @@ public static UISystem Instance
public bool TopResizing = false;
public bool BottomResizing = false;
+ ///
+ /// The current special shop whoami.
+ ///
+ /// -
+ /// -1: Disabled
+ ///
+ /// -
+ /// 0: Furnace Shop
+ ///
+ ///
+ ///
+ public int CurrentSpecialShop = -1;
+
+ public delegate void ChestUIDraw(UISystem system, SpriteBatch spriteBatch);
+
+ public event ChestUIDraw PostDrawChestUI;
+
public RenderTarget2D UI_Screen = null;
public UISystem()
@@ -34,6 +54,10 @@ public UISystem()
instance = this;
}
+ public Chest CurrentShop = new Chest(false);
+
+ public Chest OldChest = new Chest(false);
+
public override void Load()
{
base.Load();
@@ -41,6 +65,9 @@ public override void Load()
On_Main.DrawInterface += HigherInterfaceVisualEffectSupport;
On_Main.DrawCursor += ModifyUIBlockResizeCursor;
On_Main.DrawThickCursor += ModifyUIBlockResizeThickCursor;
+ On_ChestUI.DrawSlots += On_ChestUI_DrawPanel;
+ On_Main.DrawInventory += On_Main_DrawInventory;
+ IL_Main.DrawInventory += IL_Main_DrawInventory;
if (Main.netMode != NetmodeID.Server)
{
system.Load();
@@ -227,5 +254,56 @@ private void HigherInterfaceVisualEffectSupport(On_Main.orig_DrawInterface orig,
UI_Screen = null;
}
}
+
+ private void IL_Main_DrawInventory(ILContext il)
+ {
+ ILCursor c = new(il);
+ if (c.TryGotoNext(
+ MoveType.After,
+ x => x.MatchLdindU2(),
+ x => x.MatchLdelemU1(),
+ x => x.MatchBrtrue(out _),
+ x => x.MatchLdsfld(out _),
+ x => x.MatchLdsfld(out _),
+ x => x.MatchLdelemRef(),
+ x => x.MatchLdcI4(-1),
+ x => x.MatchStfld(out _),
+ x => x.MatchLdcI4(0),
+ x => x.MatchCall(out _),
+ x => x.MatchLdcI4(0),
+ x => x.MatchStloc(out _)))
+ {
+ c.EmitDelegate(CheckSpecialShopEnable_ModifyNpcShop);
+ }
+ }
+
+ private void On_ChestUI_DrawPanel(On_ChestUI.orig_DrawSlots orig, SpriteBatch spriteBatch)
+ {
+ orig(spriteBatch);
+ PostDrawChestUI?.Invoke(this, spriteBatch);
+ }
+
+ private void On_Main_DrawInventory(On_Main.orig_DrawInventory orig, Main self)
+ {
+ CheckSpecialShopEnable_ModifyNpcShop();
+ orig(self);
+ DisposeSpecialShopEnable_ModifyNpcShop();
+ }
+
+ private void CheckSpecialShopEnable_ModifyNpcShop()
+ {
+ if (CurrentSpecialShop >= 0 && Main.npcShop == 0)
+ {
+ Main.npcShop = SpecialShopWhoAmI_Zero + CurrentSpecialShop;
+ }
+ }
+
+ private void DisposeSpecialShopEnable_ModifyNpcShop()
+ {
+ if (Main.npcShop >= SpecialShopWhoAmI_Zero)
+ {
+ Main.npcShop = 0;
+ }
+ }
}
}
diff --git a/Sources/Everglow.Function/Utilities/BackgroundHelper/BackgroundHigherPerformanceHelper.cs b/Sources/Everglow.Function/Utilities/BackgroundHelper/BackgroundHigherPerformanceHelper.cs
index e563bb945..76cba3977 100644
--- a/Sources/Everglow.Function/Utilities/BackgroundHelper/BackgroundHigherPerformanceHelper.cs
+++ b/Sources/Everglow.Function/Utilities/BackgroundHelper/BackgroundHigherPerformanceHelper.cs
@@ -22,7 +22,8 @@ public static class BackgroundHigherPerformanceHelper
public static void Add_TileBgVertice(
BackgroundSlideBase bg,
List tiles,
- List bars)
+ List bars,
+ int samplingUnit = 1)
{
if (bg.UseColorStyle != 1)
{
@@ -62,7 +63,6 @@ public static void Add_TileBgVertice(
int lastY = visibleTiles[0].Pos.Y;
int lastX = visibleTiles[0].Pos.X;
- int samplingUnit = 1;
if (bg is UnderBackgroundBackgroundSlideBase)
{
UnderBackgroundBackgroundSlideBase ubg = bg as UnderBackgroundBackgroundSlideBase;
@@ -263,6 +263,26 @@ public static void Add_TileBgVertice_NolightMap(
CollectionsMarshal.SetCount(bars, currentSize);
}
+ public static void Add_WorldPosVertex(BackgroundSlideBase bg, Vector2 position, Span span, ref int currentSize)
+ {
+ Vector2 screenCenter = Main.screenPosition + new Vector2(Main.screenWidth, Main.screenHeight) * 0.5f;
+ Vector2 move = (screenCenter - bg.WorldAnchor) / bg.Distance;
+ Vector2 texcoord_Move = move / bg.Texture.Size();
+ Vector2 screenPoint = position - screenCenter;
+ Vector2 screen_move = screenPoint / bg.Texture.Size() + texcoord_Move;
+
+ Color drawColor = GetColor(bg, position);
+ span[currentSize] = new Vertex2D(position - Main.screenPosition, drawColor, new Vector3(screen_move + new Vector2(0.5f), 0));
+ currentSize++;
+ }
+
+ public static void Add_WorldTriangle(BackgroundSlideBase bg, Vector2 v0, Vector2 v1, Vector2 v2, Span span, ref int currentSize)
+ {
+ Add_WorldPosVertex(bg, v0, span, ref currentSize);
+ Add_WorldPosVertex(bg, v1, span, ref currentSize);
+ Add_WorldPosVertex(bg, v2, span, ref currentSize);
+ }
+
private static Color GetColor(BackgroundSlideBase bg, Vector2 worldPos)
{
Color c = Color.White;
diff --git a/Sources/Everglow.Function/Utilities/BackgroundHelper/BackgroundSlideBase.cs b/Sources/Everglow.Function/Utilities/BackgroundHelper/BackgroundSlideBase.cs
index a84be2edd..54dc2c9c5 100644
--- a/Sources/Everglow.Function/Utilities/BackgroundHelper/BackgroundSlideBase.cs
+++ b/Sources/Everglow.Function/Utilities/BackgroundHelper/BackgroundSlideBase.cs
@@ -28,6 +28,13 @@ public abstract class BackgroundSlideBase
///
public int UseColorStyle = 0;
+ ///
+ /// It has higher priority in ordering the layer of backgrounds then .
+ /// Larger overlap the smaller.
+ /// In most cases it should be 0.
+ ///
+ public int LayerPriority = 0;
+
public virtual bool AllowMultiple => false;
///
@@ -243,6 +250,22 @@ public static void DrawVertexBackground(BackgroundSlideBase bg, PrimitiveType pr
}
}
+ public static void DrawVertexBackground(Texture2D texture, PrimitiveType primitiveType, List bars)
+ {
+ if (bars.Count > 2)
+ {
+ Main.graphics.graphicsDevice.Textures[0] = texture;
+ if (primitiveType == PrimitiveType.TriangleList)
+ {
+ Main.graphics.graphicsDevice.DrawUserPrimitives(primitiveType, bars.ToArray(), 0, bars.Count / 3);
+ }
+ if (primitiveType == PrimitiveType.TriangleStrip)
+ {
+ Main.graphics.graphicsDevice.DrawUserPrimitives(primitiveType, bars.ToArray(), 0, bars.Count - 2);
+ }
+ }
+ }
+
public class Effects
{
public static readonly Effect XClamp_YClamp_Shader = ModAsset.BgShader_X_Clamp_Y_Clamp.Value;
diff --git a/Sources/Everglow.Function/Utilities/BackgroundHelper/BackgroundSystem.cs b/Sources/Everglow.Function/Utilities/BackgroundHelper/BackgroundSystem.cs
index 9d05f5b36..188e09f9a 100644
--- a/Sources/Everglow.Function/Utilities/BackgroundHelper/BackgroundSystem.cs
+++ b/Sources/Everglow.Function/Utilities/BackgroundHelper/BackgroundSystem.cs
@@ -54,7 +54,7 @@ private void DrawBackground()
Main.spriteBatch.End();
Main.spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointWrap, DepthStencilState.None, RasterizerState.CullNone, null, Main.Transform);
Effect lastEffect = null;
- foreach (var bg in backgroundSlides.OrderByDescending(b => b.Distance)) // Adapt to dynamic distance.
+ foreach (var bg in backgroundSlides.OrderBy(b => b.LayerPriority).ThenByDescending(b => b.Distance)) // Adapt to dynamic distance.
{
bool shouldChangeSpriteBatch = bg.Shader != lastEffect;
if (shouldChangeSpriteBatch)
@@ -109,5 +109,4 @@ public bool HasBgSlide(string uniqueName)
{
return backgroundSlides.Any(x => x.UniqueName == uniqueName);
}
-
}
diff --git a/Sources/Everglow.Function/Utilities/NPCUtils.cs b/Sources/Everglow.Function/Utilities/NPCUtils.cs
index bb5671a79..64603770c 100644
--- a/Sources/Everglow.Function/Utilities/NPCUtils.cs
+++ b/Sources/Everglow.Function/Utilities/NPCUtils.cs
@@ -1,7 +1,5 @@
using Everglow.Commons.Mechanics.ElementalDebuff;
using Everglow.Commons.Netcode.Packets;
-using Mono.Cecil.Cil;
-using MonoMod.Cil;
namespace Everglow.Commons.Utilities;
@@ -233,6 +231,14 @@ public static int GetVanillaDotDamage(this NPC npc, IEnumerable buffTypes)
public static void SetLifeRegenExpectedLossPerSecond(this NPC npc, int value) =>
npc.lifeRegenExpectedLossPerSecond = Math.Max(npc.lifeRegenExpectedLossPerSecond, value);
+ public static void StrikeNPCWithCustomCombatText(this NPC npc, NPC.HitInfo hit, Color textColor, bool dot = false)
+ {
+ npc.HideStrikeDamage = true;
+ npc.StrikeNPC(hit);
+ npc.HideStrikeDamage = false;
+ CombatText.NewText(npc.Hitbox, textColor, hit.Damage, hit.Crit, dot);
+ }
+
#endregion
#region Elemental Debuff
@@ -332,4 +338,33 @@ public static ref StatModifier GetElementalResistance(this NPC npc, string type)
ref npc.GetElementalDebuff(type).ElementalResistanceModifier;
#endregion
+
+ #region AI Utils
+
+ ///
+ /// Find the nearet npc from a given position.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static NPC FindNearest(Vector2 position, int type, float maxDistance = 2048)
+ {
+ NPC target = null;
+ float distanceMin = maxDistance;
+ foreach (var npc in Main.npc)
+ {
+ if (npc is not null && npc.active && npc.type == type)
+ {
+ float distanceNPC = (npc.Center - position).Length();
+ if (distanceNPC < distanceMin)
+ {
+ distanceMin = distanceNPC;
+ target = npc;
+ }
+ }
+ }
+ return target;
+ }
+ #endregion
}
diff --git a/Sources/Everglow.Function/Utilities/SpriteBatchUtils.cs b/Sources/Everglow.Function/Utilities/SpriteBatchUtils.cs
new file mode 100644
index 000000000..f273f58bd
--- /dev/null
+++ b/Sources/Everglow.Function/Utilities/SpriteBatchUtils.cs
@@ -0,0 +1,247 @@
+using System.Runtime.InteropServices;
+using Everglow.Commons.Vertex;
+
+namespace Everglow.Commons.Utilities;
+
+public static class SpriteBatchUtils
+{
+ public static List DrawCurveStrip_EnvironmentLight(List curve, float width, float coord_x_min, float coord_x_max, float coord_y_min = 0, float coord_y_max = 1, bool curveHasScreenPos = false)
+ {
+ if (curve.Count < 2)
+ {
+ return [];
+ }
+ Vector2 lightSamplingOffset = Vector2.zeroVector;
+ if (!curveHasScreenPos)
+ {
+ lightSamplingOffset = Main.screenPosition;
+ }
+ List bars = new List();
+ for (int i = 0; i < curve.Count; i++)
+ {
+ Vector2 pos = curve[i];
+ Vector2 dir;
+ if (i == 0)
+ {
+ dir = curve[i + 1] - curve[i];
+ }
+ else
+ {
+ dir = curve[i] - curve[i - 1];
+ }
+ dir = dir.NormalizeSafe();
+ Vector2 normal = new Vector2(dir.Y, -dir.X) * width / 2f;
+ float value = i / (float)(curve.Count - 1);
+ float coordX = float.Lerp(coord_x_min, coord_x_max, value);
+ AddVertexWithEnv_Light(bars, pos + normal + lightSamplingOffset, new Vector3(coordX, coord_y_min, 0));
+ AddVertexWithEnv_Light(bars, pos - normal + lightSamplingOffset, new Vector3(coordX, coord_y_max, 0));
+ }
+ return bars;
+ }
+
+ public static Color GetEnv_Light(Vector2 worldPosition)
+ {
+ return Lighting.GetColor(worldPosition.ToTileCoordinates());
+ }
+
+ public static void AddVertexWithEnv_Light(List bars, Vector2 worldPos, Vector3 texCoord, bool removeScreenPos = true, float colorFade = 1f)
+ {
+ Vector2 offset = Vector2.Zero;
+ if (removeScreenPos)
+ {
+ offset = -Main.screenPosition;
+ }
+ bars.Add(worldPos + offset, GetEnv_Light(worldPos + Main.screenPosition + offset) * colorFade, texCoord);
+ }
+
+ public static void AddVerticesForCircleRing(List bars, Vector2 position, float radius, float width, Color drawColor, float coorx_x_min, float coord_x_max, float coord_z = 0)
+ {
+ int currentSize = bars.Count;
+ int count = (int)(radius / 4 + 10);
+ CollectionsMarshal.SetCount(bars, count * 2 + 256);
+ Span span = CollectionsMarshal.AsSpan(bars);
+ for (int k = 0; k <= count; k++)
+ {
+ float value = k / (float)count;
+ float coordX = (float)Utils.Lerp(coorx_x_min, coord_x_max, value);
+ Vector2 pos0 = position + new Vector2(0, radius + width / 2f).RotatedBy(value * MathHelper.TwoPi);
+ Vector2 pos1 = position + new Vector2(0, radius - width / 2f).RotatedBy(value * MathHelper.TwoPi);
+ float maxCoordY = 1;
+ if (radius < width / 2f)
+ {
+ pos1 = position;
+ maxCoordY = 0.5f + radius / (width / 2f);
+ }
+ span[currentSize] = new Vertex2D(pos0, drawColor, new Vector3(coordX, 0, coord_z));
+ currentSize++;
+ span[currentSize] = new Vertex2D(pos1, drawColor, new Vector3(coordX, maxCoordY, coord_z));
+ currentSize++;
+ }
+ CollectionsMarshal.SetCount(bars, currentSize);
+ }
+
+ ///
+ /// R:0-1
G:0-1
B:0-1
+ ///
+ /// R:0-1
G:0-1
B:0-1
+ /// H:0-360
S:0-1
V:0-1
+ public static Vector3 RGBToHSV(Vector3 rgb)
+ {
+ float r = rgb.X;
+ float g = rgb.Y;
+ float b = rgb.Z;
+
+ float max = MathHelper.Max(MathHelper.Max(r, g), b);
+ float min = MathHelper.Min(MathHelper.Min(r, g), b);
+ float delta = max - min;
+
+ float h = 0f;
+ float s = max == 0 ? 0f : delta / max;
+ float v = max;
+
+ if (delta == 0)
+ {
+ h = 0f;
+ }
+ else
+ {
+ if (max == r)
+ {
+ h = ((g - b) / delta) % 6;
+ }
+ else if (max == g)
+ {
+ h = 2 + (b - r) / delta;
+ }
+ else if (max == b)
+ {
+ h = 4 + (r - g) / delta;
+ }
+
+ h *= 60;
+ if (h < 0)
+ {
+ h += 360;
+ }
+ }
+
+ return new Vector3(h, s, v);
+ }
+
+ ///
+ /// H:0-360
S:0-1
V:0-1
+ ///
+ /// H:0-360
S:0-1
V:0-1
+ /// R:0-1
G:0-1
B:0-1
+ public static Vector3 HSVToRGB(Vector3 hsv)
+ {
+ float h = hsv.X;
+ float s = hsv.Y;
+ float v = hsv.Z;
+
+ if (s == 0)
+ {
+ return new Vector3(v, v, v);
+ }
+
+ h = h % 360f;
+ if (h < 0)
+ {
+ h += 360;
+ }
+
+ float sector = h / 60f;
+ int sectorIndex = (int)Math.Floor(sector);
+ float fractional = sector - sectorIndex;
+
+ float p = v * (1 - s);
+ float q = v * (1 - s * fractional);
+ float t = v * (1 - s * (1 - fractional));
+
+ switch (sectorIndex)
+ {
+ case 0:
+ return new Vector3(v, t, p);
+ case 1:
+ return new Vector3(q, v, p);
+ case 2:
+ return new Vector3(p, v, t);
+ case 3:
+ return new Vector3(p, q, v);
+ case 4:
+ return new Vector3(t, p, v);
+ default:
+ return new Vector3(v, p, q);
+ }
+ }
+
+ ///
+ /// Transforms Vector3(H, S, V) to RGB and returns a Color with the specified alpha.
+ ///
+ /// H:0-360
S:0-1
V:0-1
+ /// 0-1
+ ///
+ public static Color HSVToRGB_Color(this Vector3 hsv, float a)
+ {
+ Vector3 rgb = HSVToRGB(hsv);
+ return new Color(rgb.X, rgb.Y, rgb.Z, a);
+ }
+
+ ///
+ /// Add vertices just like what Main.spriteBatch.Draw does. But sampling environment light at each vertex.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void AddVertex_Grid(List bars, Vector2 position, Rectangle? frame, Vector2 origin, Texture2D tex, bool screenPos = false, int gridSize = 16, float rotation = 0, float alpha = 1f)
+ {
+ var drawPos = position;
+ Vector2 pos = drawPos;
+ if (screenPos)
+ {
+ pos += Main.screenPosition;
+ }
+ Rectangle frame2 = frame ?? tex.Frame();
+ int xCount = frame2.Width / gridSize;
+ int yCount = frame2.Height / gridSize;
+ float unitX = frame2.Width / (float)xCount;
+ float unitY = frame2.Height / (float)yCount;
+ for (int x = 0; x < xCount; x++)
+ {
+ Vector2 offset_2 = (new Vector2(x * unitX, 0) - origin).RotatedBy(rotation);
+ Vector2 offset_1 = (new Vector2((x + 1) * unitX, 0) - origin).RotatedBy(rotation);
+ bars.Add(pos + offset_2, Color.Transparent, new Vector3(new Vector2(frame2.X + x * unitX, frame2.Y) / tex.Size(), 0));
+ bars.Add(pos + offset_1, Color.Transparent, new Vector3(new Vector2(frame2.X + (x + 1) * unitX, frame2.Y) / tex.Size(), 0));
+ for (int y = 0; y < yCount; y++)
+ {
+ Vector2 offset0 = (new Vector2(x * unitX, y * unitY) - origin).RotatedBy(rotation);
+ Vector2 offset1 = (new Vector2((x + 1) * unitX, y * unitY) - origin).RotatedBy(rotation);
+ Vector2 offset2 = (new Vector2(x * unitX, (y + 1) * unitY) - origin).RotatedBy(rotation);
+ Vector2 offset3 = (new Vector2((x + 1) * unitX, (y + 1) * unitY) - origin).RotatedBy(rotation);
+
+ AddLightColorVertex(bars, pos + offset0, new Vector3(new Vector2(frame2.X + x * unitX, frame2.Y + y * unitY) / tex.Size(), 0), alpha, screenPos);
+ AddLightColorVertex(bars, pos + offset1, new Vector3(new Vector2(frame2.X + (x + 1) * unitX, frame2.Y + y * unitY) / tex.Size(), 0), alpha, screenPos);
+ AddLightColorVertex(bars, pos + offset2, new Vector3(new Vector2(frame2.X + x * unitX, frame2.Y + (y + 1) * unitY) / tex.Size(), 0), alpha, screenPos);
+ AddLightColorVertex(bars, pos + offset3, new Vector3(new Vector2(frame2.X + (x + 1) * unitX, frame2.Y + (y + 1) * unitY) / tex.Size(), 0), alpha, screenPos);
+ }
+ Vector2 offset4 = (new Vector2(x * unitX, yCount * unitY) - origin).RotatedBy(rotation);
+ Vector2 offset5 = (new Vector2((x + 1) * unitX, yCount * unitY) - origin).RotatedBy(rotation);
+ bars.Add(pos + offset4, Color.Transparent, new Vector3(new Vector2(frame2.X + x * unitX, frame2.Y + yCount * unitY) / tex.Size(), 0));
+ bars.Add(pos + offset5, Color.Transparent, new Vector3(new Vector2(frame2.X + (x + 1) * unitX, frame2.Y + yCount * unitY) / tex.Size(), 0));
+ }
+ }
+
+ public static void AddLightColorVertex(List bars, Vector2 worldPos, Vector3 coord, float alpha = 1f, bool screenPos = false)
+ {
+ Color drawC = Lighting.GetColor(worldPos.ToTileCoordinates()) * alpha;
+ if (screenPos)
+ {
+ worldPos -= Main.screenPosition;
+ }
+ bars.Add(worldPos, drawC, coord);
+ }
+}
diff --git a/Sources/Everglow.Function/Utilities/TileUtils.Collision.cs b/Sources/Everglow.Function/Utilities/TileUtils.Collision.cs
index 1e143336b..605ee1fab 100644
--- a/Sources/Everglow.Function/Utilities/TileUtils.Collision.cs
+++ b/Sources/Everglow.Function/Utilities/TileUtils.Collision.cs
@@ -187,4 +187,11 @@ public static bool IsAreaEmpty(int x, int y, int width, int height)
{
return IsAreaEmpty(new Point(x, y), new Point(width, height));
}
+
+ public static bool CanPlayerInteractWithTile(int i, int j, Player player)
+ {
+ Item sItem = player.HeldItem.Clone();
+ bool flag = player.position.X / 16f - player.lastTileRangeX - sItem.tileBoost <= i && (player.position.X + player.width) / 16f + player.lastTileRangeX + sItem.tileBoost - 1f >= i && player.position.Y / 16f - player.lastTileRangeY - sItem.tileBoost <= j;
+ return flag && (player.position.Y + player.height) / 16f + player.lastTileRangeY + sItem.tileBoost - 2f >= j;
+ }
}
diff --git a/Sources/Everglow.Function/Utilities/TileUtils.WorldGen.cs b/Sources/Everglow.Function/Utilities/TileUtils.WorldGen.cs
new file mode 100644
index 000000000..79b905495
--- /dev/null
+++ b/Sources/Everglow.Function/Utilities/TileUtils.WorldGen.cs
@@ -0,0 +1,2534 @@
+using Everglow.Commons.TileHelper;
+using MathNet.Numerics.LinearAlgebra.Factorization;
+using Terraria.ObjectData;
+using Terraria.Utilities;
+
+namespace Everglow.Commons.Utilities;
+
+public partial class TileUtils
+{
+ public static int[,] PerlinPixelR = new int[512, 512];
+ public static int[,] PerlinPixelG = new int[512, 512];
+ public static int[,] PerlinPixelB = new int[512, 512];
+
+ public static int[,] LargeSmokeTexturePixelR = new int[1024, 1024];
+ public static int[,] LargeSmokeTexturePixelG = new int[1024, 1024];
+ public static int[,] LargeSmokeTexturePixelB = new int[1024, 1024];
+
+ public static UnifiedRandom GenRand = new UnifiedRandom();
+
+ ///
+ /// 0: Forceful
+ /// 1: NoTile
+ /// 2: HasTile
+ /// 3: HasWall
+ /// 4: NoWall
+ /// 5: HasLiquid
+ /// 6: NoLiquid
+ /// 7: HasTileAndWall
+ /// 8: TileButNoWallOnly
+ /// 9: WallButNoTileOnly
+ /// 10: SolidBlock
+ /// 11: NoneSolidTile
+ ///
+ public enum TileChangeState
+ {
+ Forceful,
+ NoTile,
+ HasTile,
+ HasWall,
+ NoWall,
+ HasLiquid,
+ NoLiquid,
+ HasTileAndWall,
+ TileButNoWallOnly,
+ WallButNoTileOnly,
+ SolidBlock,
+ NoneSolidTile,
+ }
+
+ public static bool CanChangeTile(Tile tile, int state)
+ {
+ switch (state)
+ {
+ case (int)TileChangeState.Forceful:
+ return true;
+ case (int)TileChangeState.NoTile:
+ if (!tile.HasTile)
+ {
+ return true;
+ }
+ break;
+ case (int)TileChangeState.HasTile:
+ if (tile.HasTile)
+ {
+ return true;
+ }
+ break;
+ case (int)TileChangeState.HasWall:
+ if (tile.wall > 0)
+ {
+ return true;
+ }
+ break;
+ case (int)TileChangeState.NoWall:
+ if (tile.wall <= 0)
+ {
+ return true;
+ }
+ break;
+ case (int)TileChangeState.HasLiquid:
+ if (tile.LiquidAmount > 0)
+ {
+ return true;
+ }
+ break;
+ case (int)TileChangeState.NoLiquid:
+ if (tile.LiquidAmount <= 0)
+ {
+ return true;
+ }
+ break;
+ case (int)TileChangeState.HasTileAndWall:
+ if (tile.wall > 0 && tile.HasTile)
+ {
+ return true;
+ }
+ break;
+ case (int)TileChangeState.TileButNoWallOnly:
+ if (tile.wall <= 0 && tile.HasTile)
+ {
+ return true;
+ }
+ break;
+ case (int)TileChangeState.WallButNoTileOnly:
+ if (tile.wall > 0 && !tile.HasTile)
+ {
+ return true;
+ }
+ break;
+ case (int)TileChangeState.SolidBlock:
+ if (tile.HasTile && IsTileSolid(tile))
+ {
+ return true;
+ }
+ break;
+ case (int)TileChangeState.NoneSolidTile:
+ if (tile.HasTile && !IsTileSolid(tile))
+ {
+ return true;
+ }
+ break;
+ }
+
+ return false;
+ }
+
+ public static void TotalInitialize()
+ {
+ GenRand = WorldGen.genRand;
+ FillPerlinPixel();
+ }
+
+ public static void FillPerlinPixel()
+ {
+ var imageData = ImageReader.Read(ModAsset.WorldGen_Noise_rgb_Mod);
+ Vector2 perlinCoordCenter = new Vector2(GenRand.NextFloat(0f, 1f), GenRand.NextFloat(0f, 1f));
+ imageData.ProcessPixelRows(accessor =>
+ {
+ for (int y = 0; y < accessor.Height; y++)
+ {
+ int newY = (int)(accessor.Height * perlinCoordCenter.Y + y) % accessor.Height;
+ var pixelRow = accessor.GetRowSpan(newY);
+ for (int x = 0; x < pixelRow.Length; x++)
+ {
+ int newX = (int)(accessor.Width * perlinCoordCenter.X + x) % accessor.Width;
+ ref var pixel = ref pixelRow[newX];
+ PerlinPixelR[x, y] = pixel.R;
+ PerlinPixelG[x, y] = pixel.G;
+ PerlinPixelB[x, y] = pixel.B;
+ }
+ }
+ });
+
+ imageData = ImageReader.Read(ModAsset.WorldGenLarge_rgb_Mod);
+ perlinCoordCenter = new Vector2(GenRand.NextFloat(0f, 1f), GenRand.NextFloat(0f, 1f));
+ imageData.ProcessPixelRows(accessor =>
+ {
+ for (int y = 0; y < accessor.Height; y++)
+ {
+ int newY = (int)(accessor.Height * perlinCoordCenter.Y + y) % accessor.Height;
+ var pixelRow = accessor.GetRowSpan(newY);
+ for (int x = 0; x < pixelRow.Length; x++)
+ {
+ int newX = (int)(accessor.Width * perlinCoordCenter.X + x) % accessor.Width;
+ ref var pixel = ref pixelRow[newX];
+ LargeSmokeTexturePixelR[x, y] = pixel.R;
+ LargeSmokeTexturePixelG[x, y] = pixel.G;
+ LargeSmokeTexturePixelB[x, y] = pixel.B;
+ }
+ }
+ });
+ }
+
+ ///
+ /// A float value based on the noise texture's red channel.
+ ///
+ /// 0f~1f
+ public static float GetPerlinPixelR(double x, double y)
+ {
+ return GetLerpTexturePixelValue(PerlinPixelR, x, y);
+ }
+
+ ///
+ /// A float value based on the noise texture's green channel.
+ ///
+ /// 0f~1f
+ public static float GetPerlinPixelG(double x, double y)
+ {
+ return GetLerpTexturePixelValue(PerlinPixelG, x, y);
+ }
+
+ ///
+ /// A float value based on the noise texture's blue channel.
+ ///
+ /// 0f~1f
+ public static float GetPerlinPixelB(double x, double y)
+ {
+ return GetLerpTexturePixelValue(PerlinPixelB, x, y);
+ }
+
+ ///
+ /// A float value based on the noise texture's red channel.
+ ///
+ /// 0f~1f
+ public static float GetLargeSmokeTexturePixelR(double x, double y)
+ {
+ return GetLerpTexturePixelValue(LargeSmokeTexturePixelR, x, y);
+ }
+
+ ///
+ /// A float value based on the noise texture's green channel.
+ ///
+ /// 0f~1f
+ public static float GetLargeSmokeTexturePixelG(double x, double y)
+ {
+ return GetLerpTexturePixelValue(LargeSmokeTexturePixelG, x, y);
+ }
+
+ ///
+ /// A float value based on the noise texture's blue channel.
+ ///
+ /// 0f~1f
+ public static float GetLargeSmokeTexturePixelB(double x, double y)
+ {
+ return GetLerpTexturePixelValue(LargeSmokeTexturePixelB, x, y);
+ }
+
+ public static float GetLerpTexturePixelValue(int[,] colorMap, double x, double y)
+ {
+ return colorMap[(int)(Math.Abs(x) % colorMap.GetLength(0)), (int)(Math.Abs(y) % colorMap.GetLength(1))] / 255f;
+ }
+
+ ///
+ /// Use (x, y) as the top left corner to place a frame important tile area with given width and height, and set the frameX and frameY of each tile in this area according to their position in this area.
+ ///
+ ///
+ public static void PlaceFrameImportantTiles(int x, int y, int width, int height, int type, int startX = 0, int startY = 0)
+ {
+ if (x > Main.maxTilesX - width || x < 0 || y > Main.maxTilesY - height || y < 0)
+ {
+ return;
+ }
+
+ for (int i = 0; i < width; i++)
+ {
+ for (int j = 0; j < height; j++)
+ {
+ Tile tile = Main.tile[x + i, y + j];
+ tile.TileType = (ushort)type;
+ tile.TileFrameX = (short)(i * 18 + startX);
+ tile.TileFrameY = (short)(j * 18 + startY);
+ tile.HasTile = true;
+ }
+ }
+ }
+
+ ///
+ /// place frame important tiles above the area with (x, y - 1) as the BOTTOM left corner and given width and height (It means that Y = y in most case should be solid tile), and set the frameX and frameY of each tile in this area according to their position in this area.
+ ///
+ /// TileFrameX at left side, +18 each tile towards right.
+ /// TileFrameX at top side, +18 each tile towards down.
+ public static void PlaceFrameImportantTilesAbove(int x, int y, int width, int height, int type, int startX = 0, int startY = 0)
+ {
+ if (x > Main.maxTilesX - width || x < 0 || y > Main.maxTilesY - height || y < 0)
+ {
+ return;
+ }
+
+ for (int i = 0; i < width; i++)
+ {
+ for (int j = 0; j < height; j++)
+ {
+ Tile tile = Main.tile[x + i, y + j - height];
+ tile.TileType = (ushort)type;
+ tile.TileFrameX = (short)(i * 18 + startX);
+ tile.TileFrameY = (short)(j * 18 + startY);
+ tile.HasTile = true;
+ }
+ }
+ }
+
+ ///
+ /// Place frame important tiles at TileObjectData.Origin.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void PlaceFrameImportantTilesAtTileObjectDataOrigin(Point tileCoord, int type, int startX = 0, int startY = 0)
+ {
+ int i = tileCoord.X;
+ int j = tileCoord.Y;
+ TileObjectData tileObjectData = TileObjectData.GetTileData(type, Main.LocalPlayer.HeldItem.placeStyle);
+ i -= tileObjectData.Origin.X;
+ j -= tileObjectData.Origin.Y;
+ int width = tileObjectData.Width;
+ int height = tileObjectData.Height;
+ for (int x = 0; x < width; x++)
+ {
+ for (int y = 0; y < height; y++)
+ {
+ var tile = SafeGetTile(x + i, y + j);
+ tile.TileType = (ushort)type;
+ tile.TileFrameX = (short)((x * 18) + startX);
+ tile.TileFrameY = (short)((y * 18) + startY);
+ tile.HasTile = true;
+ }
+ }
+ }
+
+ /// True when the given point can be killed safely(without chest).
+ public static bool ChestSafe(int x, int y)
+ {
+ Tile tile = SafeGetTile(x, y);
+ Tile tileUp = SafeGetTile(x, y - 1);
+ if (!TileID.Sets.BasicChest[tile.TileType] && !TileID.Sets.BasicChest[tileUp.TileType])
+ {
+ return true;
+ }
+ return false;
+ }
+
+ /// Tile coordinate, no world coordinate.
+ ///
+ public static bool ChestSafe(Vector2 center)
+ {
+ return ChestSafe((int)center.X, (int)center.Y);
+ }
+
+ /// True when the given tile can be killed safely(without chest).
+ public static bool ChestSafe(Tile tile)
+ {
+ return ChestSafe(tile.X(), tile.Y());
+ }
+
+ ///
+ /// Fill tiles by given area:(x0:left, y0:top, x1:right, y1:bottom)
+ ///
+ /// Left
+ /// Top
+ /// Right
+ /// Bottom
+ /// TileID: place the tile.
+ /// -1: Kill tile.
+ /// -2: ClearEverything
+ ///
+ public static void PlaceRectangleAreaOfBlock(int x0, int y0, int x1, int y1, int type, int force = 0)
+ {
+ if (x0 > x1)
+ {
+ (x0, x1) = (x1, x0);
+ }
+ if (y0 > y1)
+ {
+ (y0, y1) = (y1, y0);
+ }
+ for (int x = x0; x <= x1; x += 1)
+ {
+ for (int y = y0; y <= y1; y += 1)
+ {
+ Tile tile = SafeGetTile(x, y);
+ ChangeTile(tile, type, force);
+ }
+ }
+ }
+
+ ///
+ /// Fill tiles by given area:(x, y, w, h) where (x, y) is the top left corner.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void PlaceRectangleAreaOfBlock_XYWH(int x, int y, int w, int h, int type, int force = 0)
+ {
+ PlaceRectangleAreaOfBlock(x, y, x + w - 1, y + h - 1, type, force);
+ }
+
+ ///
+ /// Fill tiles by given area. The pos is the top left corner and size is the width and height. So the area is (pos.X, pos.Y) to (pos.X + size.X, pos.Y + size.Y).
+ ///
+ /// Tile coord.
+ ///
+ /// TileID: place the tile.
+ /// -1: Kill tile.
+ /// -2: ClearEverything
+ ///
+ public static void PlaceRectangleAreaOfBlock(Vector2 pos, Vector2 size, int type, int force = 0)
+ {
+ PlaceRectangleAreaOfBlock((int)pos.X, (int)pos.Y, (int)(size + pos).X, (int)(size + pos).Y, type, force);
+ }
+
+ ///
+ /// Set a center and radius of a circle in tile coordinate.
+ ///
+ /// Tile coord center in Vector2.
+ /// TileID: place the tile.
+ /// -1: Kill tile.
+ /// -2: ClearEverything
+ ///
+ public static void PlaceCircleAreaOfBlock(Vector2 center, float radius, int type, int force = 0)
+ {
+ int radiusI = (int)radius;
+ for (int x = -radiusI; x <= radiusI; x++)
+ {
+ for (int y = -radiusI; y <= radiusI; y++)
+ {
+ Tile tile = SafeGetTile(center + new Vector2(x, y));
+ if (new Vector2(x, y).Length() <= radius)
+ {
+ ChangeTile(tile, type, force);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Set a center and radius of a circle in tile coordinate.
+ ///
+ /// Tile coord center in Vector2.
+ /// TileID: place the tile.
+ /// -1: Kill tile.
+ /// -2: ClearEverything
+ ///
+ public static void PlaceCircleAreaOfWall(Vector2 center, float radius, int type, int force = 0)
+ {
+ int radiusI = (int)radius;
+ for (int x = -radiusI; x <= radiusI; x++)
+ {
+ for (int y = -radiusI; y <= radiusI; y++)
+ {
+ Tile tile = SafeGetTile(center + new Vector2(x, y));
+ if (new Vector2(x, y).Length() <= radius)
+ {
+ ChangeWall(tile, type, force);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Set a center and radius of a circle in tile coordinate.
+ ///
+ /// Tile coord center in Vector2.
+ /// TileID: place the tile.
+ /// -1: Kill tile.
+ /// -2: ClearEverything
+ ///
+ public static void PlaceCircleAreaOfLiquid(Vector2 center, float radius, int type, int force = 0)
+ {
+ int radiusI = (int)radius;
+ for (int x = -radiusI; x <= radiusI; x++)
+ {
+ for (int y = -radiusI; y <= radiusI; y++)
+ {
+ Tile tile = SafeGetTile(center + new Vector2(x, y));
+ if (new Vector2(x, y).Length() <= radius)
+ {
+ ChangeLiquid(tile, type, force);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Set a center and radius of a circle in tile coordinate.
+ ///
+ /// TileID: place the tile.
+ /// -1: Kill tile.
+ /// -2: ClearEverything
+ ///
+ public static void PlaceCircleAreaOfBlock(Point center, float radius, int type, int force = 0)
+ {
+ PlaceCircleAreaOfBlock(center.ToVector2(), radius, type, force);
+ }
+
+ ///
+ /// Set a center and radius of a circle in tile coordinate.
+ ///
+ /// TileID: place the tile.
+ /// -1: Kill tile.
+ /// -2: ClearEverything
+ ///
+ public static void PlaceCircleAreaOfWall(Point center, float radius, int type, int force = 0)
+ {
+ PlaceCircleAreaOfWall(center.ToVector2(), radius, type, force);
+ }
+
+ ///
+ /// Set a center and radius of a circle in tile coordinate.
+ ///
+ /// TileID: place the tile.
+ /// -1: Kill tile.
+ /// -2: ClearEverything
+ ///
+ public static void PlaceCircleAreaOfLiquid(Point center, float radius, int type, int force = 0)
+ {
+ PlaceCircleAreaOfLiquid(center.ToVector2(), radius, type, force);
+ }
+
+ ///
+ /// Get a list of tile coordinates in a circle area with random noise.
+ ///
+ /// the center of the circle
+ /// the radius of the circle
+ /// the max random noise that can be added to the radius
+ ///
+ public static List GetCircleAreaOfTilePosWithRandomNoise(Point pos, float radius, float noiseSize = 3f)
+ {
+ List tiles = new List();
+ int x0CoordPerlin = GenRand.Next(512);
+ int y0CoordPerlin = GenRand.Next(512);
+ int radiusI = (int)radius;
+ for (int x = -radiusI; x <= radiusI; x++)
+ {
+ for (int y = -radiusI; y <= radiusI; y++)
+ {
+ float aValue = GetPerlinPixelR(x + x0CoordPerlin, y + y0CoordPerlin);
+ if (new Vector2(x, y).Length() <= radius - aValue * noiseSize)
+ {
+ tiles.Add(new Point(x, y) + pos);
+ }
+ }
+ }
+ return tiles;
+ }
+
+ ///
+ /// Get a list of tile coordinates in a circle area with random noise.
+ ///
+ /// the center of the circle
+ /// the radius of the circle
+ /// the max random noise that can be added to the radius
+ ///
+ public static List GetCircleAreaOfTilePos(Point pos, float radius)
+ {
+ List tiles = new List();
+ int radiusI = (int)(radius + 1);
+ for (int x = -radiusI; x <= radiusI; x++)
+ {
+ for (int y = -radiusI; y <= radiusI; y++)
+ {
+ if (new Vector2(x, y).Length() <= radius)
+ {
+ tiles.Add(new Point(x, y) + pos);
+ }
+ }
+ }
+ return tiles;
+ }
+
+ ///
+ /// Transform the tile within the circle(center, radius) to the type, but with a random noise affect on the bound.
+ ///
+ /// Tile coord center in Vector2.
+ /// TileID: place the tile.
+ /// -1: Kill tile.
+ /// -2: ClearEverything
+ ///
+ public static void PlaceCircleAreaOfBlockWithRandomNoise(Vector2 center, float radius, int type, float noiseSize = 3f, int force = 0)
+ {
+ int x0CoordPerlin = GenRand.Next(512);
+ int y0CoordPerlin = GenRand.Next(512);
+ int radiusI = (int)radius;
+ for (int x = -radiusI; x <= radiusI; x++)
+ {
+ for (int y = -radiusI; y <= radiusI; y++)
+ {
+ float aValue = GetPerlinPixelR(x + x0CoordPerlin, y + y0CoordPerlin);
+ if (new Vector2(x, y).Length() <= radius - aValue * noiseSize)
+ {
+ Tile tile = SafeGetTile(center + new Vector2(x, y));
+ ChangeTile(tile, type, force);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Transform the tile within the circle(center, radius) to the type, but with a random noise affect on the bound.
+ ///
+ /// TileID: place the tile.
+ /// -1: Kill tile.
+ /// -2: ClearEverything
+ ///
+ public static void PlaceCircleAreaOfBlockWithRandomNoise(Point center, float radius, int type, float noiseSize = 10f, int force = 0)
+ {
+ PlaceCircleAreaOfBlockWithRandomNoise(center.ToVector2(), radius, type, noiseSize, force);
+ }
+
+ ///
+ /// Transform the wall within the circle(center, radius) to the type, but with a random noise affect on the bound.
+ ///
+ /// Tile coord
+ ///
+ ///
+ ///
+ ///
+ public static void PlaceCircleAreaOfWallWithRandomNoise(Point center, float radius, int type, float noiseSize = 10f, int force = 0)
+ {
+ PlaceCircleAreaOfWallWithRandomNoise(center.ToVector2(), radius, type, noiseSize, force);
+ }
+
+ ///
+ /// Transform the wall within the circle(center, radius) to the type, but with a random noise affect on the bound.
+ ///
+ /// Tile coord
+ ///
+ ///
+ ///
+ ///
+ public static void PlaceCircleAreaOfWallWithRandomNoise(Vector2 center, float radius, int type, float noiseSize = 3f, int force = 0)
+ {
+ int x0CoordPerlin = GenRand.Next(512);
+ int y0CoordPerlin = GenRand.Next(512);
+ int radiusI = (int)radius;
+ for (int x = -radiusI; x <= radiusI; x++)
+ {
+ for (int y = -radiusI; y <= radiusI; y++)
+ {
+ float aValue = GetPerlinPixelR(x + x0CoordPerlin, y + y0CoordPerlin);
+ if (new Vector2(x, y).Length() <= radius - aValue * noiseSize)
+ {
+ Tile tile = SafeGetTile(center + new Vector2(x, y));
+ ChangeWall(tile, type, force);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Kill the tile within the circle(center, radius), but with a random noise affect on the bound.
+ ///
+ /// Tile coord
+ ///
+ ///
+ /// -1: Kill tile.
+ /// -2: ClearEverything
+ ///
+ ///
+ public static void KillCircleAreaOfBlockWithRandomNoiseInCertainTypeOfTile(Vector2 center, float radius, List type_be_killed, int killStyle = -1, float noiseSize = 10f, int force = 0)
+ {
+ int x0CoordPerlin = GenRand.Next(512);
+ int y0CoordPerlin = GenRand.Next(512);
+ int radiusI = (int)radius;
+ for (int x = -radiusI; x <= radiusI; x++)
+ {
+ for (int y = -radiusI; y <= radiusI; y++)
+ {
+ float aValue = GetPerlinPixelR(x + x0CoordPerlin, y + y0CoordPerlin);
+ Tile tile = SafeGetTile(center + new Vector2(x, y));
+ if (new Vector2(x, y).Length() <= radius - aValue * noiseSize && type_be_killed.Contains(tile.TileType))
+ {
+ ChangeTile(tile, killStyle, force);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Kill the tile within the circle(center, radius), but with a random noise affect on the bound.
+ ///
+ /// Tile coord
+ ///
+ ///
+ /// -1: Kill tile.
+ /// -2: ClearEverything
+ ///
+ ///
+ public static void KillCircleAreaOfBlockWithRandomNoiseInCertainTypeOfTile(Point center, float radius, List type_be_killed, int killStyle = -1, float noiseSize = 10f, int force = 0)
+ {
+ KillCircleAreaOfBlockWithRandomNoiseInCertainTypeOfTile(center.ToVector2(), radius, type_be_killed, killStyle, noiseSize, force);
+ }
+
+ ///
+ /// Kill the wall within the circle(center, radius), but with a random noise affect on the bound.
+ ///
+ ///
+ ///
+ ///
+ /// Default to 0, only wall will be removed.
+ ///
+ ///
+ public static void KillCircleAreaOfWallWithRandomNoiseInCertainType(Point center, float radius, List type_be_killed, int killStyle = 0, float noiseSize = 10f, int force = 0)
+ {
+ int x0CoordPerlin = GenRand.Next(512);
+ int y0CoordPerlin = GenRand.Next(512);
+ int radiusI = (int)radius;
+ for (int x = -radiusI; x <= radiusI; x++)
+ {
+ for (int y = -radiusI; y <= radiusI; y++)
+ {
+ float aValue = GetPerlinPixelR(x + x0CoordPerlin, y + y0CoordPerlin);
+ Tile tile = SafeGetTile(center + new Point(x, y));
+ if (new Vector2(x, y).Length() <= radius - aValue * noiseSize && type_be_killed.Contains(tile.wall))
+ {
+ ChangeWall(tile, killStyle, force);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Transform the tile within the polygon to the type. The polygon is a list of WORLD coordinates in Vector2, and the area is determined by the point-in-polygon test.
+ ///
+ /// WORLD coord
+ ///
+ ///
+ public static void PlacePolygonAreaOfBlock(List polygon, int type, int force = 0)
+ {
+ if (polygon.Count < 3)
+ {
+ return;
+ }
+ var bounds = MathUtils.GetPolygonAABBBound_Vector4(polygon);
+ for (int x = (int)bounds.X - 8; x < bounds.Z; x += 16)
+ {
+ for (int y = (int)bounds.Y - 8; y < bounds.W; y += 16)
+ {
+ if (MathUtils.IsPointInPolygon(polygon, new Vector2(x, y)))
+ {
+ Tile tile = SafeGetTile(new Vector2(x, y).ToTileCoordinates());
+ ChangeTile(tile, type, force);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Transform the tiles within the polygon to the type. The polygon is a list of TILE coordinates in Point, and the area is determined by the point-in-polygon test.
+ ///
+ /// TILE coord
+ ///
+ ///
+ public static void PlacePolygonAreaOfBlock(List polygon, int type, int force = 0)
+ {
+ List polygon_Vector2 = new List();
+ foreach (var point in polygon)
+ {
+ polygon_Vector2.Add(point.ToWorldCoordinates());
+ }
+ PlacePolygonAreaOfBlock(polygon_Vector2, type, force);
+ }
+
+ ///
+ /// Transform the walls within the polygon to the type. The polygon is a list of WORLD coordinates in Vector2, and the area is determined by the point-in-polygon test.
+ ///
+ /// WORLD coord
+ ///
+ ///
+ public static void PlacePolygonAreaOfWall(List polygon, int type, int force = 0)
+ {
+ if (polygon.Count < 3)
+ {
+ return;
+ }
+ var bounds = MathUtils.GetPolygonAABBBound_Vector4(polygon);
+ for (int x = (int)bounds.X; x <= bounds.Z; x += 16)
+ {
+ for (int y = (int)bounds.Y; y <= bounds.W; y += 16)
+ {
+ if (MathUtils.IsPointInPolygon(polygon, new Vector2(x, y)))
+ {
+ Tile tile = SafeGetTile(new Vector2(x, y).ToTileCoordinates());
+ ChangeWall(tile, type, force);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Transform the liquid within the polygon to the type. The polygon is a list of WORLD coordinates in Vector2, and the area is determined by the point-in-polygon test.
+ ///
+ /// WORLD coord
+ ///
+ ///
+ public static void PlacePolygonAreaOfLiquid(List polygon, int type, int force = 0)
+ {
+ if (polygon.Count < 3)
+ {
+ return;
+ }
+ var bounds = MathUtils.GetPolygonAABBBound_Vector4(polygon);
+ for (int x = (int)bounds.X; x <= bounds.Z; x += 16)
+ {
+ for (int y = (int)bounds.Y; y <= bounds.W; y += 16)
+ {
+ if (MathUtils.IsPointInPolygon(polygon, new Vector2(x, y)))
+ {
+ Tile tile = SafeGetTile(new Vector2(x, y).ToTileCoordinates());
+ ChangeLiquid(tile, type, force);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Transform the tile within the polygon to the type. The polygon is a list of TILE coordinates in Point, and the area is determined by the point-in-polygon test.
+ ///
+ /// TILE coord
+ ///
+ ///
+ public static void PlacePolygonAreaOfWall(List polygon, int type, int force = 0)
+ {
+ List polygon_Vector2 = new List();
+ foreach (var point in polygon)
+ {
+ polygon_Vector2.Add(point.ToWorldCoordinates());
+ }
+ PlacePolygonAreaOfWall(polygon_Vector2, type, force);
+ }
+
+ ///
+ /// Automatically offset the polygon by the anchorPos, then transform the tile within the polygon to the type. The polygon is a list of WORLD coordinates in Vector2, and the area is determined by the point-in-polygon test.
+ ///
+ /// WORLD coord
+ ///
+ ///
+ ///
+ public static void PlacePolygonAreaOfBlockWithOffset(List polygon, Vector2 anchorPos, int type, int force = 0)
+ {
+ if (polygon.Count < 3)
+ {
+ return;
+ }
+ List newPolygon = polygon;
+ for (int i = 0; i < newPolygon.Count; i++)
+ {
+ newPolygon[i] += anchorPos;
+ }
+ PlacePolygonAreaOfBlock(newPolygon, type, force);
+ }
+
+ ///
+ /// Automatically offset the polygon by the anchorPos, then transform the tile within the polygon to the type. The polygon is a list of TILE coordinates in Point, and the area is determined by the point-in-polygon test.
+ ///
+ /// TILE coord
+ ///
+ ///
+ ///
+ public static void PlacePolygonAreaOfBlockWithOffset(List polygon, Vector2 anchorPos, int type, int force = 0)
+ {
+ List polygon_Vector2 = new List();
+ foreach (var point in polygon)
+ {
+ polygon_Vector2.Add(point.ToWorldCoordinates());
+ }
+ PlacePolygonAreaOfBlockWithOffset(polygon_Vector2, anchorPos, type, force);
+ }
+
+ ///
+ /// Transform the tiles at the edge of the polygon to the type. The polygon is a list of WORLD coordinates in Vector2, and the area is determined by the point-in-polygon test.
+ ///
+ /// WORLD coord
+ ///
+ /// WORLD coord
+ ///
+ public static void PlacePolygonBoundOfBlock(List polygon, int type, float thick, int force = 0)
+ {
+ if (polygon.Count < 3)
+ {
+ return;
+ }
+ for (int k = 0; k < polygon.Count; k++)
+ {
+ int nextIndex = k + 1;
+ if (nextIndex == polygon.Count)
+ {
+ nextIndex = 0;
+ }
+ PlaceLineBlock(polygon[k], polygon[nextIndex], thick, type, force);
+ }
+ }
+
+ ///
+ /// Transform the tiles at the edge of the polygon to the type. The polygon is a list of TILE coordinates in Point, and the area is determined by the point-in-polygon test.
+ ///
+ /// TILE coord
+ ///
+ ///
+ ///
+ public static void PlacePolygonBoundOfBlock(List polygon, int type, float thick, int force = 0)
+ {
+ List polygon_Vector2 = new List();
+ foreach (var point in polygon)
+ {
+ polygon_Vector2.Add(point.ToWorldCoordinates());
+ }
+ PlacePolygonBoundOfBlock(polygon_Vector2, type, thick, force);
+ }
+
+ ///
+ /// Transform the tiles at the edge of the polygon to the type. The polygon is a list of WORLD coordinates in Vector2, and the area is determined by the point-in-polygon test.
+ ///
+ /// WORLD coord
+ ///
+ /// WORLD coord
+ ///
+ public static void PlacePolygonBoundOfWall(List polygon, int type, float thick, int force = 0)
+ {
+ if (polygon.Count < 3)
+ {
+ return;
+ }
+ for (int k = 0; k < polygon.Count; k++)
+ {
+ int nextIndex = k + 1;
+ if (nextIndex == polygon.Count)
+ {
+ nextIndex = 0;
+ }
+ PlaceLineWall(polygon[k], polygon[nextIndex], thick, type, force);
+ }
+ }
+
+ ///
+ /// Transform the tiles at the edge of the polygon to the type. The polygon is a list of TILE coordinates in Point, and the area is determined by the point-in-polygon test.
+ ///
+ /// TILE coord
+ ///
+ /// WORLD coord
+ ///
+ public static void PlacePolygonBoundOfWall(List polygon, int type, float thick, int force = 0)
+ {
+ List polygon_Vector2 = new List();
+ foreach (var point in polygon)
+ {
+ polygon_Vector2.Add(point.ToWorldCoordinates());
+ }
+ PlacePolygonBoundOfWall(polygon_Vector2, type, thick, force);
+ }
+
+ ///
+ /// Transform the tiles beside the line(pos0, pos1) to the type. Notice that thick is in World Coord, 16 for a tile size.
+ ///
+ /// WORLD coord
+ /// WORLD coord
+ /// WORLD coord
+ ///
+ public static void PlaceLineBlock(Vector2 pos0, Vector2 pos1, float thick, int type, int force = 0)
+ {
+ Vector2 dir = pos0 - pos1;
+ if (dir == Vector2.zeroVector)
+ {
+ return;
+ }
+ Vector2 normalizedDir = dir.NormalizeSafe().RotatedBy(MathHelper.PiOver2);
+ List tiltRect = new List();
+ tiltRect.Add(pos0 + normalizedDir * thick * 0.5f);
+ tiltRect.Add(pos1 + normalizedDir * thick * 0.5f);
+ tiltRect.Add(pos1 - normalizedDir * thick * 0.5f);
+ tiltRect.Add(pos0 - normalizedDir * thick * 0.5f);
+ PlacePolygonAreaOfBlock(tiltRect, type, force);
+ }
+
+ ///
+ /// Transform the tiles beside the line(pos0, pos1) to the type. Notice that thick is in World Coord, 16 for a tile size.
+ ///
+ /// TILE coord
+ /// TILE coord
+ ///
+ ///
+ ///
+ public static void PlaceLineBlock(Point pos0, Point pos1, float thick, int type, int force = 0)
+ {
+ PlaceLineBlock(pos0.ToWorldCoordinates(), pos1.ToWorldCoordinates(), thick, type, force);
+ }
+
+ ///
+ /// Transform the walls beside the line(pos0, pos1) to the type. Notice that thick is in World Coord, 16 for a tile size.
+ ///
+ /// WORLD coord
+ /// WORLD coord
+ /// WORLD coord
+ ///
+ ///
+ public static void PlaceLineWall(Vector2 pos0, Vector2 pos1, float thick, int type, int force = 0)
+ {
+ Vector2 dir = pos0 - pos1;
+ if (dir == Vector2.zeroVector)
+ {
+ return;
+ }
+ Vector2 normalizedDir = dir.NormalizeSafe().RotatedBy(MathHelper.PiOver2);
+ List tiltRect = new List();
+ tiltRect.Add(pos0 + normalizedDir * thick * 0.5f);
+ tiltRect.Add(pos1 + normalizedDir * thick * 0.5f);
+ tiltRect.Add(pos1 - normalizedDir * thick * 0.5f);
+ tiltRect.Add(pos0 - normalizedDir * thick * 0.5f);
+ PlacePolygonAreaOfWall(tiltRect, type, force);
+ }
+
+ ///
+ /// Transform the liquid beside the line(pos0, pos1) to the type. Notice that thick is in World Coord, 16 for a tile size.
+ ///
+ /// WORLD coord
+ /// WORLD coord
+ /// WORLD coord
+ ///
+ ///
+ public static void PlaceLineLiquid(Vector2 pos0, Vector2 pos1, float thick, int type, int force = 0)
+ {
+ Vector2 dir = pos0 - pos1;
+ if (dir == Vector2.zeroVector)
+ {
+ return;
+ }
+ Vector2 normalizedDir = dir.NormalizeSafe().RotatedBy(MathHelper.PiOver2);
+ List tiltRect = new List();
+ tiltRect.Add(pos0 + normalizedDir * thick * 0.5f);
+ tiltRect.Add(pos1 + normalizedDir * thick * 0.5f);
+ tiltRect.Add(pos1 - normalizedDir * thick * 0.5f);
+ tiltRect.Add(pos0 - normalizedDir * thick * 0.5f);
+ PlacePolygonAreaOfLiquid(tiltRect, type, force);
+ }
+
+ ///
+ /// Transform the walls beside the line(pos0, pos1) to the type. Notice that thick is in World Coord, 16 for a tile size.
+ ///
+ /// TILE coord
+ /// TILE coord
+ /// WORLD coord
+ ///
+ public static void PlaceLineWall(Point pos0, Point pos1, float thick, int type, int force = 0)
+ {
+ PlaceLineWall(pos0.ToWorldCoordinates(), pos1.ToWorldCoordinates(), thick, type, force);
+ }
+
+ ///
+ /// Transform the liquid beside the line(pos0, pos1) to the type. Notice that thick is in World Coord, 16 for a tile size.
+ ///
+ /// TILE coord
+ /// TILE coord
+ /// WORLD coord
+ ///
+ public static void PlaceLineLiquid(Point pos0, Point pos1, float thick, int type, int force = 0)
+ {
+ PlaceLineLiquid(pos0.ToWorldCoordinates(), pos1.ToWorldCoordinates(), thick, type, force);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void ChangeTile(Tile tile, int type, int force)
+ {
+ if (ChestSafe(tile) && CanChangeTile(tile, force))
+ {
+ if (type >= 0)
+ {
+ tile.TileType = (ushort)type;
+ tile.HasTile = true;
+ }
+ else if (type == -1)
+ {
+ tile.HasTile = false;
+ }
+ else if (type == -2)
+ {
+ tile.ClearEverything();
+ }
+ }
+ }
+
+ public static void ChangeWall(Tile tile, int type, int force)
+ {
+ if (ChestSafe(tile) && CanChangeTile(tile, force))
+ {
+ if (type >= 0)
+ {
+ tile.WallType = (ushort)type;
+ }
+ else if (type == -1)
+ {
+ tile.HasTile = false;
+ }
+ else if (type == -2)
+ {
+ tile.ClearEverything();
+ }
+ }
+ }
+
+ public static void ChangeLiquid(Tile tile, int type, int force)
+ {
+ if (ChestSafe(tile) && CanChangeTile(tile, force))
+ {
+ if (type >= 0)
+ {
+ tile.LiquidType = (ushort)type;
+ }
+ else if (type == -1)
+ {
+ tile.HasTile = false;
+ }
+ else if (type == -2)
+ {
+ tile.ClearEverything();
+ }
+ }
+ }
+
+ ///
+ /// Smooth tiles by given area:(x0:left, y0:top, x1:right, y1:bottom)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void SmoothTile_XXYY(int x0, int y0, int x1, int y1)
+ {
+ x0 = Math.Clamp(x0, 20, Main.maxTilesX - 20);
+ x1 = Math.Clamp(x1, 20, Main.maxTilesX - 20);
+ y0 = Math.Clamp(y0, 20, Main.maxTilesY - 20);
+ y1 = Math.Clamp(y1, 20, Main.maxTilesY - 20);
+ for (int x = x0; x <= x1; x += 1)
+ {
+ for (int y = y0; y <= y1; y += 1)
+ {
+ if (!ChestSafe(x, y))
+ {
+ continue;
+ }
+ Tile.SmoothSlope(x, y, false, false);
+ WorldGen.TileFrame(x, y, true, false);
+ WorldGen.SquareWallFrame(x, y, true);
+ }
+ }
+ }
+
+ ///
+ /// Smooth tiles by given area:(x, y, w, h)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void SmoothTile_XYWH(int x, int y, int w, int h)
+ {
+ SmoothTile_XXYY(x, y, x + w, y + h);
+ }
+
+ ///
+ /// Smooth tiles by given tile list. Note that the tile list should be in the same area, otherwise it may cause some unexpected result.
+ ///
+ ///
+ public static void SmoothTile_List(List tiles)
+ {
+ foreach (var pos in tiles)
+ {
+ if (!ChestSafe(pos.X, pos.Y))
+ {
+ continue;
+ }
+ Tile.SmoothSlope(pos.X, pos.Y, false, false);
+ WorldGen.TileFrame(pos.X, pos.Y, true, true);
+ WorldGen.SquareWallFrame(pos.X, pos.Y, true);
+ }
+ }
+
+ public static void SmoothTile_PolygonArea(List polygon_TilePos)
+ {
+ List polygon_WorldPos = new List();
+ foreach (var point in polygon_TilePos)
+ {
+ polygon_WorldPos.Add(point.ToWorldCoordinates());
+ }
+ SmoothTile_PolygonArea(polygon_WorldPos);
+ }
+
+ public static void SmoothTile_PolygonArea(List polygon_WorldPos)
+ {
+ if (polygon_WorldPos.Count < 3)
+ {
+ return;
+ }
+ var bounds = MathUtils.GetPolygonAABBBound_Vector4(polygon_WorldPos);
+ for (int x = (int)bounds.X; x <= bounds.Z; x += 16)
+ {
+ for (int y = (int)bounds.Y; y <= bounds.W; y += 16)
+ {
+ if (MathUtils.IsPointInPolygon(polygon_WorldPos, new Vector2(x, y)))
+ {
+ var point = new Vector2(x, y).ToTileCoordinates();
+ Tile.SmoothSlope(point.X, point.Y, false, false);
+ WorldGen.TileFrame(point.X, point.Y, true, true);
+ WorldGen.SquareWallFrame(point.X, point.Y, true);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Use BFS algorithm get the continue tiles from the check point.
+ ///
+ ///
+ /// If true, tile with no block but only wall will also be included.
+ ///
+ ///
+ public static List BFSContinueTile(Point checkPoint, bool includeWall = false, int maxCount = 512, List theseTypeOnly = default)
+ {
+ int maxContinueCount = maxCount;
+ (int, int)[] directions =
+ {
+ (0, 1),
+ (1, 0),
+ (0, -1),
+ (-1, 0),
+ };
+ Queue queueChecked = new Queue();
+
+ // Add first point to the queue.
+ queueChecked.Enqueue(checkPoint);
+ List visited = new List();
+
+ while (queueChecked.Count > 0)
+ {
+ var tilePos = queueChecked.Dequeue();
+
+ foreach (var (dx, dy) in directions)
+ {
+ int checkX = tilePos.X + dx;
+ int checkY = tilePos.Y + dy;
+ Point point = new Point(checkX, checkY);
+ Tile tile = SafeGetTile(checkX, checkY);
+
+ // Check bound and obstruction.
+ if (checkX >= 20 && checkX < Main.maxTilesX - 20 && checkY >= 20 && checkY < Main.maxTilesY - 20 &&
+ (tile.HasTile || (includeWall && tile.WallType > WallID.None)) && !visited.Contains(point))
+ {
+ if (theseTypeOnly == default)
+ {
+ queueChecked.Enqueue(point);
+ visited.Add(point);
+ }
+ else if (theseTypeOnly.Contains(tile.TileType))
+ {
+ queueChecked.Enqueue(point);
+ visited.Add(point);
+ }
+ }
+ }
+ if (queueChecked.Count > maxContinueCount || visited.Count > maxContinueCount)
+ {
+ break;
+ }
+ }
+ return visited;
+ }
+
+ public static List BFSContinueWall(Point checkPoint, int maxCount = 512, List theseTypeOnly = default)
+ {
+ int maxContinueCount = maxCount;
+ (int, int)[] directions =
+ {
+ (0, 1),
+ (1, 0),
+ (0, -1),
+ (-1, 0),
+ };
+ Queue queueChecked = new Queue();
+
+ // Add first point to the queue.
+ queueChecked.Enqueue(checkPoint);
+ List visited = new List();
+
+ while (queueChecked.Count > 0)
+ {
+ var tilePos = queueChecked.Dequeue();
+
+ foreach (var (dx, dy) in directions)
+ {
+ int checkX = tilePos.X + dx;
+ int checkY = tilePos.Y + dy;
+ Point point = new Point(checkX, checkY);
+ Tile tile = SafeGetTile(checkX, checkY);
+
+ // Check bound and obstruction.
+ if (checkX >= 20 && checkX < Main.maxTilesX - 20 && checkY >= 20 && checkY < Main.maxTilesY - 20 &&
+ (tile.WallType > WallID.None || theseTypeOnly.Contains(WallID.None)) && !visited.Contains(point))
+ {
+ if (theseTypeOnly == default)
+ {
+ queueChecked.Enqueue(point);
+ visited.Add(point);
+ }
+ else if (theseTypeOnly.Contains(tile.WallType))
+ {
+ queueChecked.Enqueue(point);
+ visited.Add(point);
+ }
+ }
+ }
+ if (queueChecked.Count > maxContinueCount || visited.Count > maxContinueCount)
+ {
+ break;
+ }
+ }
+ return visited;
+ }
+
+ ///
+ /// Use BFS algorithm get the continue tiles from the check point.
+ ///
+ ///
+ /// If true, tile is empty but has wall will NOT count as empty.
+ ///
+ ///
+ public static List BFSContinueEmpty(Point checkPoint, bool includeWall = false, int maxCount = 512, List ignoreTheseType = default)
+ {
+ int maxContinueCount = maxCount;
+ (int, int)[] directions =
+ {
+ (0, 1),
+ (1, 0),
+ (0, -1),
+ (-1, 0),
+ };
+ Queue queueChecked = new Queue();
+
+ // Add first point to the queue.
+ queueChecked.Enqueue(checkPoint);
+ List visited = new List();
+
+ while (queueChecked.Count > 0)
+ {
+ var tilePos = queueChecked.Dequeue();
+
+ foreach (var (dx, dy) in directions)
+ {
+ int checkX = tilePos.X + dx;
+ int checkY = tilePos.Y + dy;
+ Point point = new Point(checkX, checkY);
+ Tile tile = SafeGetTile(checkX, checkY);
+
+ // Check bound and obstruction.
+ bool flag0 = !tile.HasTile && (!includeWall || tile.WallType <= WallID.None);
+ bool flag1 = tile.HasTile && ignoreTheseType != default && ignoreTheseType.Contains(tile.TileType);
+ if (checkX >= 20 && checkX < Main.maxTilesX - 20 && checkY >= 20 && checkY < Main.maxTilesY - 20 &&
+ (flag0 || flag1) && !visited.Contains(point))
+ {
+ queueChecked.Enqueue(point);
+ visited.Add(point);
+ }
+ }
+ if (queueChecked.Count > maxContinueCount || visited.Count > maxContinueCount)
+ {
+ break;
+ }
+ }
+ return visited;
+ }
+
+ public static List BFSSurface(Point checkPoint, int maxCount = 512, bool ignoreFrameImportant = true, List theseTypeOnly = default)
+ {
+ int maxContinueCount = maxCount;
+ (int, int)[] directions =
+ {
+ (0, 1),
+ (1, 0),
+ (0, -1),
+ (-1, 0),
+
+ // (1, 1),
+ // (1, -1),
+ // (-1, -1),
+ // (-1, 1),
+ };
+ Queue queueChecked = new Queue();
+
+ // Add first point to the queue.
+ queueChecked.Enqueue(checkPoint);
+ List visited_air = new List();
+ List visited_tile = new List();
+ while (queueChecked.Count > 0)
+ {
+ var tilePos = queueChecked.Dequeue();
+
+ foreach (var (dx, dy) in directions)
+ {
+ int checkX = tilePos.X + dx;
+ int checkY = tilePos.Y + dy;
+ Point point = new Point(checkX, checkY);
+ Tile tile = SafeGetTile(checkX, checkY);
+ Tile tile_up = SafeGetTile(checkX, checkY - 1);
+ Tile tile_bottom = SafeGetTile(checkX, checkY + 1);
+ Tile tile_left = SafeGetTile(checkX - 1, checkY);
+ Tile tile_right = SafeGetTile(checkX + 1, checkY);
+
+ // Tile tile_upleft = SafeGetTile(checkX - 1, checkY - 1);
+ // Tile tile_bottomleft = SafeGetTile(checkX - 1, checkY + 1);
+ // Tile tile_upright = SafeGetTile(checkX + 1, checkY - 1);
+ // Tile tile_bottomright = SafeGetTile(checkX + 1, checkY - 1);
+
+ // bool flag0 = !tile_upleft.HasTile || !tile_upright.HasTile || !tile_bottomleft.HasTile || !tile_bottomright.HasTile;
+ // Check bound and obstruction.
+ bool flag0 = checkX >= 20 && checkX < Main.maxTilesX - 20 && checkY >= 20 && checkY < Main.maxTilesY - 20;
+ bool flag1 = tile.HasTile && (visited_air.Contains(new Point(checkX, checkY - 1)) || visited_air.Contains(new Point(checkX, checkY + 1)) || visited_air.Contains(new Point(checkX - 1, checkY)) || visited_air.Contains(new Point(checkX + 1, checkY)));
+ bool flag2 = !tile.HasTile && (tile_up.HasTile || tile_bottom.HasTile || tile_left.HasTile || tile_right.HasTile);
+ bool flag3 = !ignoreFrameImportant || !Main.tileFrameImportant[tile.TileType];
+ if (flag0 && (flag1 || flag2) && flag3 && !visited_air.Contains(point) && !visited_tile.Contains(point))
+ {
+ if (theseTypeOnly == default)
+ {
+ queueChecked.Enqueue(point);
+ if (flag1)
+ {
+ visited_tile.Add(point);
+ }
+ if (flag2)
+ {
+ visited_air.Add(point);
+ }
+ }
+ else if (theseTypeOnly.Contains(tile.TileType))
+ {
+ queueChecked.Enqueue(point);
+ if (flag1)
+ {
+ visited_tile.Add(point);
+ }
+ if (flag2)
+ {
+ visited_air.Add(point);
+ }
+ }
+ }
+ }
+ if (queueChecked.Count > maxContinueCount || visited_tile.Count + visited_air.Count > maxContinueCount)
+ {
+ break;
+ }
+ }
+ return visited_tile;
+ }
+
+ public static List GenerateRandomSeeds(int xBoundLeft, int xBoundRight, int yBoundTop, int yBoundBottom, int expect_Count, float minDistance = 20)
+ {
+ List result = new List();
+ HashSet used = new HashSet();
+
+ int width = xBoundRight - xBoundLeft;
+ int height = yBoundBottom - yBoundTop;
+ float cellSize = minDistance / (float)Math.Sqrt(2);
+ int gridW = (int)Math.Ceiling(width / cellSize) + 2;
+ int gridH = (int)Math.Ceiling(height / cellSize) + 2;
+
+ Point?[,] grid = new Point?[gridW, gridH];
+ List active = new List();
+
+ int startX = (xBoundLeft + xBoundRight) / 2;
+ int startY = (yBoundTop + yBoundBottom) / 2;
+ result.Add(new Point(startX, startY));
+ used.Add(new Point(startX, startY));
+ active.Add(new Point(startX, startY));
+ SetGrid(grid, cellSize, xBoundLeft, yBoundTop, startX, startY);
+
+ while (active.Count > 0 && result.Count < expect_Count)
+ {
+ int idx = Main.rand.Next(active.Count);
+ var current = active[idx];
+ bool found = false;
+
+ for (int i = 0; i < 8; i++)
+ {
+ float angle = Main.rand.NextFloat(0f, MathHelper.TwoPi);
+ float dist = Main.rand.NextFloat(minDistance, minDistance * 2f);
+
+ int newX = current.X + (int)Math.Round(Math.Cos(angle) * dist);
+ int newY = current.Y + (int)Math.Round(Math.Sin(angle) * dist);
+
+ if (newX < xBoundLeft || newX > xBoundRight ||
+ newY < yBoundTop || newY > yBoundBottom)
+ {
+ continue;
+ }
+
+ int gx = (int)((newX - xBoundLeft) / cellSize);
+ int gy = (int)((newY - yBoundTop) / cellSize);
+
+ bool tooClose = false;
+
+ for (int cx = Math.Max(0, gx - 1); cx <= Math.Min(gridW - 1, gx + 1); cx++)
+ {
+ for (int cy = Math.Max(0, gy - 1); cy <= Math.Min(gridH - 1, gy + 1); cy++)
+ {
+ var pt = grid[cx, cy];
+ if (pt.HasValue)
+ {
+ float d = Vector2.Distance(
+ new Vector2(newX, newY),
+ new Vector2(pt.Value.X, pt.Value.Y));
+ if (d < minDistance)
+ {
+ tooClose = true;
+ break;
+ }
+ }
+ }
+ if (tooClose)
+ {
+ break;
+ }
+ }
+
+ if (!tooClose && !used.Contains(new Point(newX, newY)))
+ {
+ result.Add(new Point(newX, newY));
+ used.Add(new Point(newX, newY));
+ active.Add(new Point(newX, newY));
+ SetGrid(grid, cellSize, xBoundLeft, yBoundTop, newX, newY);
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ active.RemoveAt(idx);
+ }
+ }
+
+ return result;
+ }
+
+ private static void SetGrid(Point?[,] grid, float cellSize, int ox, int oy, int x, int y)
+ {
+ int gx = (int)((x - ox) / cellSize);
+ int gy = (int)((y - oy) / cellSize);
+ grid[gx, gy] = new Point(x, y);
+ }
+
+ public static bool TileAtOriginPos(Tile tile)
+ {
+ int style = TileObjectData.GetTileStyle(tile);
+ TileObjectData tileObjectData = TileObjectData.GetTileData(tile.TileType, style);
+ return tile.TileFrameX - style * tileObjectData.Width * 18 == tileObjectData.Origin.X * 18 && tile.TileFrameY == tileObjectData.Origin.Y * 18;
+ }
+
+ public static void PlaceWallAround(Tile tile, int wallType, bool middle = true, bool top = true, bool bottom = true, bool left = true, bool right = true)
+ {
+ PlaceWallAround(tile.X(), tile.Y(), wallType, middle, top, bottom, left, right);
+ }
+
+ public static void PlaceWallAround(Point pos, int wallType, bool middle = true, bool top = true, bool bottom = true, bool left = true, bool right = true)
+ {
+ PlaceWallAround(pos.X, pos.Y, wallType, middle, top, bottom, left, right);
+ }
+
+ public static void PlaceWallAround(int x, int y, int wallType, bool middle = true, bool top = true, bool bottom = true, bool left = true, bool right = true)
+ {
+ Tile tile = SafeGetTile(x, y);
+ if (middle)
+ {
+ tile.wall = (ushort)wallType;
+ }
+ Tile tile_top = SafeGetTile(x, y - 1);
+ if (top)
+ {
+ tile_top.wall = (ushort)wallType;
+ }
+ Tile tile_bottom = SafeGetTile(x, y + 1);
+ if (bottom)
+ {
+ tile_bottom.wall = (ushort)wallType;
+ }
+ Tile tile_left = SafeGetTile(x - 1, y);
+ if (left)
+ {
+ tile_left.wall = (ushort)wallType;
+ }
+ Tile tile_right = SafeGetTile(x + 1, y);
+ if (right)
+ {
+ tile_right.wall = (ushort)wallType;
+ }
+ }
+
+ public static void PlaceTileAround(int x, int y, int tileType, bool middle = true, bool top = true, bool bottom = true, bool left = true, bool right = true, int force = 0)
+ {
+ Tile tile = SafeGetTile(x, y);
+ if (middle)
+ {
+ ChangeTile(tile, tileType, force);
+ }
+ Tile tile_top = SafeGetTile(x, y - 1);
+ if (top)
+ {
+ ChangeTile(tile_top, tileType, force);
+ }
+ Tile tile_bottom = SafeGetTile(x, y + 1);
+ if (bottom)
+ {
+ ChangeTile(tile_bottom, tileType, force);
+ }
+ Tile tile_left = SafeGetTile(x - 1, y);
+ if (left)
+ {
+ ChangeTile(tile_left, tileType, force);
+ }
+ Tile tile_right = SafeGetTile(x + 1, y);
+ if (right)
+ {
+ ChangeTile(tile_right, tileType, force);
+ }
+ }
+
+ private static readonly (int, int)[] directionsLiquid =
+ {
+ (1, 0),
+ (0, 1),
+ (-1, 0),
+ };
+
+ ///
+ /// Fill water or other liquid below pos. pos : in World coord.
+ ///
+ ///
+ ///
+ ///
+ public static void FillLiquid(Point pos, int type = 0, int maxCount = 900)
+ {
+ Queue queueChecked = new Queue();
+
+ // å°†èµ·å§‹ç‚¹åŠ å…¥é˜Ÿåˆ—
+ queueChecked.Enqueue(pos);
+ List visited = new List();
+
+ while (queueChecked.Count > 0)
+ {
+ var tilePos = queueChecked.Dequeue();
+
+ foreach (var (dx, dy) in directionsLiquid)
+ {
+ int checkX = tilePos.X + dx;
+ int checkY = tilePos.Y + dy;
+ Point point = new Point(checkX, checkY);
+
+ // 检查边界和障ç¢ç‰©
+ if (checkX >= 20 && checkX < Main.maxTilesX - 20 && checkY >= 20 && checkY < Main.maxTilesY - 20 &&
+ !Collision.IsWorldPointSolid(point.ToWorldCoordinates()) && !visited.Contains(point))
+ {
+ queueChecked.Enqueue(point);
+ visited.Add(point);
+ }
+ }
+ if (queueChecked.Count > maxCount || visited.Count > maxCount)
+ {
+ break;
+ }
+ }
+ if (visited.Count < maxCount)
+ {
+ foreach (var checked_pos in visited)
+ {
+ Tile tile = SafeGetTile(checked_pos);
+ tile.LiquidType = (byte)type;
+ tile.LiquidAmount = 255;
+ }
+ }
+ }
+
+ ///
+ /// Fill water or other liquid below center.center : in World coord.
+ ///
+ /// World coord
+ ///
+ public static void FillLiquid(Vector2 center, int type = 0, int maxCount = 900)
+ {
+ FillLiquid(center.ToTileCoordinates(), type, maxCount);
+ }
+
+ ///
+ /// Fill water or other liquid below pos.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void FillLiquid(int i, int j, int type = 0, int maxCount = 900)
+ {
+ FillLiquid(new Point(i, j), type, maxCount);
+ }
+
+ ///
+ /// Fill water or other liquid below center.center : in tile coord.
+ ///
+ /// Tile coord
+ public static List BFSGetCanFillLiquidTiles(Vector2 center, int maxCount = 900)
+ {
+ return BFSGetCanFillLiquidTiles(center.ToTileCoordinates(), maxCount);
+ }
+
+ ///
+ /// Fill water or other liquid below pos. pos : in tile coord.
+ ///
+ /// Tile coord
+ public static List BFSGetCanFillLiquidTiles(Point pos, int maxCount = 900)
+ {
+ Queue queueChecked = new Queue();
+
+ // å°†èµ·å§‹ç‚¹åŠ å…¥é˜Ÿåˆ—
+ queueChecked.Enqueue(pos);
+ List visited = new List();
+
+ while (queueChecked.Count > 0)
+ {
+ var tilePos = queueChecked.Dequeue();
+
+ foreach (var (dx, dy) in directionsLiquid)
+ {
+ int checkX = tilePos.X + dx;
+ int checkY = tilePos.Y + dy;
+ Tile Tile = SafeGetTile(checkX, checkY);
+ Point point = new Point(checkX, checkY);
+
+ // 检查边界和障ç¢ç‰©
+ if (checkX >= 20 && checkX < Main.maxTilesX - 20 && checkY >= 20 && checkY < Main.maxTilesY - 20 &&
+ !Collision.IsWorldPointSolid(new Point(checkX, checkY).ToWorldCoordinates()) && !visited.Contains(point))
+ {
+ queueChecked.Enqueue(new Point(checkX, checkY));
+ visited.Add(point);
+ }
+ }
+ if (queueChecked.Count > maxCount || visited.Count > maxCount)
+ {
+ break;
+ }
+ }
+ return visited;
+ }
+
+ public static List BFSGetCanFillLiquidTiles(int i, int j, int maxCount = 900)
+ {
+ return BFSGetCanFillLiquidTiles(new Point(i, j), maxCount);
+ }
+
+ ///
+ /// Get the nearest tile of the type. type : tile type, -1 : empty tile, -2 : empty tile without wall. maxDistance : the max distance to check. return : the offset to the nearest tile of the type. if no tile of the type is found within maxDistance, return new Vector2(maxDistance + 1).
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Vector2 ToNearestTypeOfTile(int x, int y, int type, float maxDistance = 100)
+ {
+ Vector2 direction = new Vector2(maxDistance + 1);
+ float minDis = maxDistance;
+ for (int i = -(int)maxDistance; i <= maxDistance; i++)
+ {
+ for (int j = -(int)maxDistance; j <= maxDistance; j++)
+ {
+ Tile tile = SafeGetTile(i + x, j + y);
+ bool flag0 = tile.HasTile && tile.TileType == type;
+ bool flag1 = type == -1 && !tile.HasTile;
+ bool flag2 = type == -2 && !tile.HasTile && tile.wall <= 0;
+ if (flag0 || flag1 || flag2)
+ {
+ Vector2 v1 = new Vector2(i, j);
+ if (v1.Length() < minDis)
+ {
+ minDis = v1.Length();
+ direction = v1;
+ }
+ }
+ }
+ }
+ return direction * 16;
+ }
+
+ ///
+ /// Get the nearest tile of the type. type : tile type, -1 : empty tile, -2 : empty tile without wall. maxDistance : the max distance to check. return : the offset to the nearest tile of the type. if no tile of the type is found within maxDistance, return Vector2.zeroVector.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Vector2 ToNearestTypeOfTile(Vector2 worldPos, int type, float maxDistance = 100)
+ {
+ int x = worldPos.ToTileCoordinates().X;
+ int y = worldPos.ToTileCoordinates().Y;
+ return ToNearestTypeOfTile(x, y, type, maxDistance);
+ }
+
+ ///
+ /// Return the summary of air-to-tile distances of given point to top and to bottom.
+ ///
+ ///
+ ///
+ ///
+ public static int CheckSpaceHeight(int x, int y)
+ {
+ int count = 0;
+ int x0 = x;
+ int y0 = y;
+ if (x0 > Main.maxTilesX || x0 < 0)
+ {
+ return count;
+ }
+ while (!SafeGetTile(x0, y0).HasTile)
+ {
+ if (y0 > Main.maxTilesY)
+ {
+ break;
+ }
+ y0++;
+ count++;
+ }
+ x0 = x;
+ y0 = y - 1;
+ while (!SafeGetTile(x0, y0).HasTile)
+ {
+ if (y0 < 0)
+ {
+ break;
+ }
+ y0--;
+ count++;
+ }
+ return count;
+ }
+
+ ///
+ /// Return the summary of air-to-tile distances of given point to left and to right.
+ ///
+ ///
+ ///
+ ///
+ public static int CheckSpaceWidth(int x, int y)
+ {
+ int count = 0;
+ int x0 = x;
+ int y0 = y;
+ if (y0 > Main.maxTilesY || y0 < 0)
+ {
+ return count;
+ }
+ while (!SafeGetTile(x0, y0).HasTile)
+ {
+ if (x0 > Main.maxTilesX)
+ {
+ break;
+ }
+ x0++;
+ count++;
+ }
+ x0 = x - 1;
+ y0 = y;
+ while (!SafeGetTile(x0, y0).HasTile)
+ {
+ if (x0 < 0)
+ {
+ break;
+ }
+ x0--;
+ count++;
+ }
+ return count;
+ }
+
+ ///
+ /// Return the air-to-tile distance from given point to LEFT.
+ ///
+ ///
+ ///
+ ///
+ public static int CheckSpaceLeft(int x, int y, bool ignore_none_solid = false)
+ {
+ int count = 0;
+ int x0 = x;
+ int y0 = y;
+ if (y0 > Main.maxTilesY || y0 < 0)
+ {
+ return count;
+ }
+ while (!SafeGetTile(x0, y0).HasTile || (!IsTileSolid(x0, y0) && ignore_none_solid))
+ {
+ if (x0 < 0)
+ {
+ break;
+ }
+ x0--;
+ count++;
+ }
+ return count;
+ }
+
+ ///
+ /// Return the air-to-tile distance from given point to RIGHT.
+ ///
+ ///
+ ///
+ ///
+ public static int CheckSpaceRight(int x, int y, bool ignore_none_solid = false)
+ {
+ int count = 0;
+ int x0 = x;
+ int y0 = y;
+ if (y0 > Main.maxTilesY || y0 < 0)
+ {
+ return count;
+ }
+ while (!SafeGetTile(x0, y0).HasTile || (!IsTileSolid(x0, y0) && ignore_none_solid))
+ {
+ if (x0 > Main.maxTilesX)
+ {
+ break;
+ }
+ x0++;
+ count++;
+ }
+ return count;
+ }
+
+ ///
+ /// Return the air-to-tile distance from given point to TOP.
+ ///
+ ///
+ ///
+ ///
+ public static int CheckSpaceUp(int x, int y, bool ignore_none_solid = false)
+ {
+ int count = 0;
+ int x0 = x;
+ int y0 = y;
+ if (x0 > Main.maxTilesX || x0 < 0)
+ {
+ return count;
+ }
+ while (!SafeGetTile(x0, y0).HasTile || (!IsTileSolid(x0, y0) && ignore_none_solid))
+ {
+ if (y0 < 0)
+ {
+ break;
+ }
+ y0--;
+ count++;
+ }
+ return count;
+ }
+
+ ///
+ /// Return the air-to-tile distance from given point to BOTTOM.
+ ///
+ ///
+ ///
+ ///
+ public static int CheckSpaceDown(int x, int y, bool ignore_none_solid = false)
+ {
+ int count = 0;
+ int x0 = x;
+ int y0 = y;
+ if (y0 > Main.maxTilesY || y0 < 0)
+ {
+ return count;
+ }
+ while (!SafeGetTile(x0, y0).HasTile || (!IsTileSolid(x0, y0) && ignore_none_solid))
+ {
+ if (y0 > Main.maxTilesY)
+ {
+ break;
+ }
+ y0++;
+ count++;
+ }
+ return count;
+ }
+
+ public static int CheckSpaceHeight(Point pos)
+ {
+ return CheckSpaceHeight(pos.X, pos.Y);
+ }
+
+ public static int CheckSpaceWidth(Point pos)
+ {
+ return CheckSpaceWidth(pos.X, pos.Y);
+ }
+
+ public static int CheckSpaceLeft(Point pos, bool ignore_none_solid = false)
+ {
+ return CheckSpaceLeft(pos.X, pos.Y, ignore_none_solid);
+ }
+
+ public static int CheckSpaceRight(Point pos, bool ignore_none_solid = false)
+ {
+ return CheckSpaceRight(pos.X, pos.Y, ignore_none_solid);
+ }
+
+ public static int CheckSpaceUp(Point pos, bool ignore_none_solid = false)
+ {
+ return CheckSpaceUp(pos.X, pos.Y, ignore_none_solid);
+ }
+
+ public static int CheckSpaceDown(Point pos, bool ignore_none_solid = false)
+ {
+ return CheckSpaceDown(pos.X, pos.Y, ignore_none_solid);
+ }
+
+ ///
+ /// Return the tile type if all tiles in the given area are the same, otherwise return -3.No any tile, return -1. If the area is out of world, return -4.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static int GetUniformTile(int x, int y, int w, int h)
+ {
+ if (x < 0 || y < 0 || x + w > Main.maxTilesX || y + h > Main.maxTilesY)
+ {
+ return -4;
+ }
+
+ Tile tile = SafeGetTile(x, y);
+ int targetId = tile.TileType;
+ if (!tile.HasTile)
+ {
+ targetId = -1;
+ }
+ for (int px = x; px < x + w; px++)
+ {
+ for (int py = y; py < y + h; py++)
+ {
+ Tile checkTile = SafeGetTile(px, py);
+ int checkType = checkTile.TileType;
+ if (!checkTile.HasTile)
+ {
+ checkType = -1;
+ }
+ if (checkType != targetId)
+ {
+ return -3;
+ }
+ }
+ }
+
+ return targetId;
+ }
+
+ ///
+ /// Return the tile type if all tiles in the given area are the same, otherwise return -3.No any tile, return -1. If the area is out of world, return -4.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static int GetUniformTile(Point point, int w, int h)
+ {
+ return GetUniformTile(point.X, point.Y, w, h);
+ }
+
+ ///
+ /// Fill liquid in the given area. Type: vanilla Liquid.ID.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void PlaceRectangleAreaOfLiquid_XYWH(int x, int y, int w, int h, int type)
+ {
+ for (int i = x; i <= x + w; i++)
+ {
+ for (int j = y; j <= y + h; j++)
+ {
+ Tile tile = SafeGetTile(i, j);
+ if (ChestSafe(x, y))
+ {
+ tile.liquid = (byte)type;
+ tile.LiquidAmount = 255;
+ }
+ }
+ }
+ }
+
+ ///
+ /// Fill all chest by given area if exist.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void FillChestXYWH(int x, int y, int width, int height, List- contents)
+ {
+ for (int i = 0; i < width; i++)
+ {
+ for (int j = 0; j < height; j++)
+ {
+ WorldGenMisc.TryFillChest(x + i, y + j, contents);
+ }
+ }
+ }
+
+ ///
+ /// Tile coord. Ignore platforms.
+ ///
+ ///
+ ///
+ public static bool IsTileSolid(Point point)
+ {
+ if (!WorldGen.InWorld(point.X, point.Y, 1))
+ {
+ return false;
+ }
+ Tile tile = Main.tile[point.X, point.Y];
+ return IsTileSolid(tile);
+ }
+
+ public static bool IsTileSolid(int x, int y)
+ {
+ return IsTileSolid(new Point(x, y));
+ }
+
+ public static bool IsTileSolid(Tile tile)
+ {
+ if (tile == null || !tile.HasTile || tile.IsActuated || !Main.tileSolid[tile.TileType])
+ {
+ return false;
+ }
+ if (tile.TileType > TileID.Dirt && (TileID.Sets.Platforms[tile.TileType] || tile.TileType == TileID.PlanterBox))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ ///
+ /// Get the tile positions in the given polygon area. World coord.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static List GetPolygonAreaOfTilePos(List polygon)
+ {
+ List polygon_Pos = new List();
+ if (polygon.Count < 3)
+ {
+ return polygon_Pos;
+ }
+ var bounds = MathUtils.GetPolygonAABBBound_Vector4(polygon);
+ bounds.X = bounds.X - bounds.X % 16 - 8;
+ bounds.Y = bounds.Y - bounds.Y % 16 - 8;
+ bounds.Z = bounds.Z - bounds.Z % 16 + 8;
+ bounds.W = bounds.W - bounds.W % 16 + 8;
+ for (int x = (int)bounds.X; x <= bounds.Z; x += 16)
+ {
+ for (int y = (int)bounds.Y; y <= bounds.W; y += 16)
+ {
+ if (MathUtils.IsPointInPolygon(polygon, new Vector2(x, y)))
+ {
+ polygon_Pos.Add(new Vector2(x, y).ToTileCoordinates());
+ }
+ }
+ }
+ return polygon_Pos;
+ }
+
+ ///
+ /// Get the tile positions in the given polygon area. Tile coord.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static List GetPolygonAreaOfTilePos(List polygon)
+ {
+ List polygon_Vector2 = new List();
+ foreach (var point in polygon)
+ {
+ polygon_Vector2.Add(point.ToWorldCoordinates());
+ }
+ return GetPolygonAreaOfTilePos(polygon_Vector2);
+ }
+
+ ///
+ /// Get the tile positions in the given rectangle area. World coord.
+ ///
+ ///
+ ///
+ public static List GetAABBAreaOfTile(Vector2 worldPos, Vector2 size)
+ {
+ List tilePoses = new List();
+ for (int x = worldPos.ToTileCoordinates().X; x <= (worldPos + size).ToTileCoordinates().X; x++)
+ {
+ for (int y = worldPos.ToTileCoordinates().Y; y <= (worldPos + size).ToTileCoordinates().Y; y++)
+ {
+ tilePoses.Add(new Point(x, y));
+ }
+ }
+ return tilePoses;
+ }
+
+ ///
+ /// Get the tile positions in the given rectangle area. Tile coord.
+ ///
+ ///
+ ///
+ public static List GetAABBAreaOfTile(int x, int y, int w, int h)
+ {
+ int minX = Math.Min(x, x + w);
+ int minY = Math.Min(y, y + h);
+ int maxX = Math.Max(x, x + w);
+ int maxY = Math.Max(y, y + h);
+ List tilePoses = new List();
+ for (int i = minX; i <= maxX; i++)
+ {
+ for (int j = minY; j <= maxY; j++)
+ {
+ tilePoses.Add(new Point(i, j));
+ }
+ }
+ return tilePoses;
+ }
+
+ ///
+ /// Get the tile positions in the given rectangle area. Tile coord.
+ ///
+ ///
+ ///
+ public static List GetAABBAreaOfTile(Point start, Point end)
+ {
+ int minX = Math.Min(start.X, end.X);
+ int minY = Math.Min(start.Y, end.Y);
+ int maxX = Math.Max(start.X, end.X);
+ int maxY = Math.Max(start.Y, end.Y);
+ List tilePoses = new List();
+ for (int x = minX; x <= maxX; x++)
+ {
+ for (int y = minY; y <= maxY; y++)
+ {
+ tilePoses.Add(new Point(x, y));
+ }
+ }
+ return tilePoses;
+ }
+
+ public static void PlaceTileListTowardDownUntilCollide(Point pos, int type, int max = 1024)
+ {
+ for (int t = 0; t < max; t++)
+ {
+ var tile = SafeGetTile(pos + new Point(0, t));
+ if (!tile.HasTile || !Main.tileSolid[tile.TileType])
+ {
+ tile.TileType = (ushort)type;
+ tile.HasTile = true;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ public static void PlaceTileListTowardUpUntilCollide(Point pos, int type, int max = 1024)
+ {
+ for (int t = 0; t < max; t++)
+ {
+ var tile = SafeGetTile(pos + new Point(0, -t));
+ if (!tile.HasTile)
+ {
+ tile.TileType = (ushort)type;
+ tile.HasTile = true;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ public static void PlaceTileListTowardLeftUntilCollide(Point pos, int type, int max = 1024)
+ {
+ for (int t = 0; t < max; t++)
+ {
+ var tile = SafeGetTile(pos + new Point(-t, 0));
+ if (!tile.HasTile)
+ {
+ tile.TileType = (ushort)type;
+ tile.HasTile = true;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ public static void PlaceTileListTowardRightUntilCollide(Point pos, int type, int max = 1024)
+ {
+ for (int t = 0; t < max; t++)
+ {
+ var tile = SafeGetTile(pos + new Point(t, 0));
+ if (!tile.HasTile)
+ {
+ tile.TileType = (ushort)type;
+ tile.HasTile = true;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ public static Point PointLerp(Point pos0, Point pos1, float value)
+ {
+ return new Point((int)(pos0.X + (pos1.X - pos0.X) * value), (int)(pos0.Y + (pos1.Y - pos0.Y) * value));
+ }
+
+ ///
+ /// Get the centroid of the given points.
+ ///
+ ///
+ ///
+ public static Point GetCentroid(List points)
+ {
+ if (points.Count <= 0)
+ {
+ return default;
+ }
+ Point point = new Point(0, 0);
+ foreach (var p in points)
+ {
+ point += p;
+ }
+ return new Point(point.X / points.Count, point.Y / points.Count);
+ }
+
+ ///
+ /// Find the nearest tile position with tile within 100 range. Return default if not found.
+ ///
+ ///
+ /// , Default to 10, SolidTile
+ ///
+ public static Point FindNearestTileWithin100Range(Point pos, int force = 10)
+ {
+ float minDis = 100;
+ Point point = default;
+ for (int i = -100; i <= 100; i++)
+ {
+ for (int j = -100; j <= 100; j++)
+ {
+ Tile tile = SafeGetTile(i + pos.X, j + pos.Y);
+ if (CanChangeTile(tile, force))
+ {
+ Vector2 v1 = new Vector2(i, j);
+ if (v1.Length() < minDis)
+ {
+ minDis = v1.Length();
+ point = new Point(i + pos.X, j + pos.Y);
+ }
+ }
+ }
+ }
+ return point;
+ }
+
+ public static float PointDistance(Point p0, Point p1)
+ {
+ return Vector2.Distance(p0.ToVector2(), p1.ToVector2());
+ }
+
+ public static void ConnectWire(Point point0, Point point1, bool red = true, bool green = false, bool blue = false, bool yellow = false)
+ {
+ int distanceX = Math.Abs((point1 - point0).X);
+ int distanceY = Math.Abs((point1 - point0).Y);
+ Point check = point0;
+ int dirX = 1;
+ int dirY = 1;
+ if (point1.X < point0.X)
+ {
+ dirX = -1;
+ }
+ if (point1.Y < point0.Y)
+ {
+ dirY = -1;
+ }
+ for (int y = 0; y < distanceY; y++)
+ {
+ Tile tile = SafeGetTile(check);
+ tile.RedWire = red;
+ tile.GreenWire = green;
+ tile.BlueWire = blue;
+ tile.YellowWire = yellow;
+ check.Y += dirY;
+ }
+ for (int x = 0; x <= distanceX; x++)
+ {
+ Tile tile = SafeGetTile(check);
+ tile.RedWire = red;
+ tile.GreenWire = green;
+ tile.BlueWire = blue;
+ tile.YellowWire = yellow;
+ check.X += dirX;
+ }
+ }
+
+ ///
+ /// Transform the tiles beside the curve to the type. Notice that thick is in World Coord, 16 for a tile size.
+ ///
+ /// Tile Coord
+ /// World Coord
+ ///
+ ///
+ public static void PlaceCurveBlock(List curve, float thick, int type, int force = 0)
+ {
+ for (int k = 0; k < curve.Count - 1; k++)
+ {
+ PlaceLineBlock(curve[k], curve[k + 1], thick, type, force);
+ if (k >= 1)
+ {
+ PlaceCircleAreaOfBlock(curve[k], thick / 32, type, force);
+ }
+ }
+ }
+
+ ///
+ /// Transform the tiles beside the curve to the type. Notice that thick is in World Coord, 16 for a tile size.
+ ///
+ /// Tile Coord
+ /// World Coord
+ ///
+ ///
+ public static void PlaceCurveWall(List curve, float thick, int type, int force = 0)
+ {
+ for (int k = 0; k < curve.Count - 1; k++)
+ {
+ PlaceLineWall(curve[k], curve[k + 1], thick, type, force);
+ if (k >= 1)
+ {
+ PlaceCircleAreaOfWall(curve[k], thick / 32, type, force);
+ }
+ }
+ }
+
+ ///
+ /// Transform the liquid beside the curve to the type. Notice that thick is in World Coord, 16 for a tile size.
+ ///
+ /// Tile Coord
+ /// World Coord
+ ///
+ ///
+ public static void PlaceCurveLiquid(List curve, float thick, int type, int force = 0)
+ {
+ for (int k = 0; k < curve.Count - 1; k++)
+ {
+ PlaceLineLiquid(curve[k], curve[k + 1], thick, type, force);
+ if (k >= 1)
+ {
+ PlaceCircleAreaOfLiquid(curve[k], thick / 32, type, force);
+ }
+ }
+ }
+
+ ///
+ /// Transform the tiles beside the curve to the type. Notice that thick is in World Coord, 16 for a tile size.
+ ///
+ /// World Coord
+ /// World Coord
+ ///
+ ///
+ public static void PlaceCurveBlock(List curve, float thick, int type, int force = 0)
+ {
+ List curve_Point = new List();
+ foreach (var pos in curve)
+ {
+ curve_Point.Add(pos.ToTileCoordinates());
+ }
+ PlaceCurveBlock(curve_Point, thick, type, force);
+ }
+
+ ///
+ /// Transform the tiles beside the curve to the type. Notice that thick is in World Coord, 16 for a tile size.
+ ///
+ /// World Coord
+ /// World Coord
+ ///
+ ///
+ public static void PlaceCurveWall(List curve, float thick, int type, int force = 0)
+ {
+ List curve_Point = new List();
+ foreach (var pos in curve)
+ {
+ curve_Point.Add(pos.ToTileCoordinates());
+ }
+ PlaceCurveWall(curve_Point, thick, type, force);
+ }
+
+ ///
+ /// Transform the liquid beside the curve to the type. Notice that thick is in World Coord, 16 for a tile size.
+ ///
+ /// World Coord
+ /// World Coord
+ ///
+ ///
+ public static void PlaceCurveLiquid(List curve, float thick, int type, int force = 0)
+ {
+ List curve_Point = new List();
+ foreach (var pos in curve)
+ {
+ curve_Point.Add(pos.ToTileCoordinates());
+ }
+ PlaceCurveLiquid(curve_Point, thick, type, force);
+ }
+
+ ///
+ /// Place a prefabricated MapIO anchored top left at (x, y).
+ ///
+ ///
+ ///
+ ///
+ public static void BuildMapIO(int x, int y, string path)
+ {
+ var mapIO = new MapIO(x, y);
+ mapIO.Read(ModIns.Mod.GetFileStream(path));
+ var it = mapIO.GetEnumerator();
+ while (it.MoveNext())
+ {
+ WorldGen.SquareTileFrame(it.CurrentCoord.X, it.CurrentCoord.Y);
+ WorldGen.SquareWallFrame(it.CurrentCoord.X, it.CurrentCoord.Y);
+ }
+ }
+
+ public static void BuildMapIO(Point point, string path)
+ {
+ BuildMapIO(point.X, point.Y, path);
+ }
+}
diff --git a/Sources/Everglow.Function/Utilities/TileUtils.cs b/Sources/Everglow.Function/Utilities/TileUtils.cs
index 95169bc84..e0ef28da4 100644
--- a/Sources/Everglow.Function/Utilities/TileUtils.cs
+++ b/Sources/Everglow.Function/Utilities/TileUtils.cs
@@ -1,3 +1,8 @@
+using Everglow.Commons.Vertex;
+using Terraria.DataStructures;
+using Terraria.Enums;
+using Terraria.ObjectData;
+
namespace Everglow.Commons.Utilities;
public partial class TileUtils
@@ -18,51 +23,74 @@ public static Tile SafeGetTile(int i, int j) =>
public static Tile SafeGetTile(Point point) => SafeGetTile(point.X, point.Y);
- public static Tile SafeGetTile(Vector2 vector) => SafeGetTile((int)vector.X, (int)vector.Y);
-
///
- /// 以[x,y]为左上顶点放置大件连ç»ç‰©å—,æ¤ç±»ç‰©å—必须是18x18(ä¸ç®—分隔线就16x16)一帧的
+ /// The vector is expected to be the tile coordinate, not world coordinate. (i.e. vector.X is expected to be i, and vector.Y is expected to be j)
///
- ///
+ ///
///
- public static void PlaceFrameImportantTiles(int x, int y, int width, int height, int type, int startX = 0, int startY = 0)
+ public static Tile SafeGetTile(Vector2 vector) => SafeGetTile((int)vector.X, (int)vector.Y);
+
+ public static void DefaultToMultiTileAnchorBottom(int width, int height)
{
- if (x > Main.maxTilesX - width || x < 0 || y > Main.maxTilesY - height || y < 0)
- {
- return;
- }
+ TileObjectData.newTile.CopyFrom(TileObjectData.Style1x1);
+ TileObjectData.newTile.Height = height;
+ TileObjectData.newTile.Width = width;
+ TileObjectData.newTile.StyleHorizontal = true;
+ TileObjectData.newTile.CoordinateHeights = new int[height];
+ Array.Fill(TileObjectData.newTile.CoordinateHeights, 16);
+ TileObjectData.newTile.CoordinateHeights[^1] = 18;
+ TileObjectData.newTile.CoordinateWidth = 16;
+ TileObjectData.newTile.Origin = new Point16(width / 2, height - 1);
+ TileObjectData.newTile.AnchorBottom = new AnchorData(AnchorType.SolidTile, width, 0);
+ }
- for (int i = 0; i < width; i++)
- {
- for (int j = 0; j < height; j++)
- {
- Tile tile = Main.tile[x + i, y + j];
- tile.TileType = (ushort)type;
- tile.TileFrameX = (short)(i * 18 + startX);
- tile.TileFrameY = (short)(j * 18 + startY);
- tile.HasTile = true;
- }
- }
+ public static void DefaultToMultiTileAnchorTop(int width, int height)
+ {
+ TileObjectData.newTile.CopyFrom(TileObjectData.Style1x1);
+ TileObjectData.newTile.Height = height;
+ TileObjectData.newTile.Width = width;
+ TileObjectData.newTile.StyleHorizontal = true;
+ TileObjectData.newTile.CoordinateHeights = new int[height];
+ Array.Fill(TileObjectData.newTile.CoordinateHeights, 16);
+ TileObjectData.newTile.CoordinateHeights[^1] = 18;
+ TileObjectData.newTile.CoordinateWidth = 16;
+ TileObjectData.newTile.Origin = new Point16(width / 2, height - 1);
+ TileObjectData.newTile.AnchorTop = new AnchorData(AnchorType.SolidTile, width, 0);
}
- public static void PlaceFrameImportantTilesAbove(int x, int y, int width, int height, int type, int startX = 0, int startY = 0)
+ public static void DefaultToMultiTileWall(int width, int height)
{
- if (x > Main.maxTilesX - width || x < 0 || y > Main.maxTilesY - height || y < 0)
- {
- return;
- }
+ TileObjectData.newTile.CopyFrom(TileObjectData.Style3x3Wall);
+ TileObjectData.newTile.Height = height;
+ TileObjectData.newTile.Width = width;
+ TileObjectData.newTile.CoordinateHeights = new int[height];
+ Array.Fill(TileObjectData.newTile.CoordinateHeights, 16);
+ TileObjectData.newTile.Origin = new Point16(width / 2, height / 2);
+ TileObjectData.newTile.StyleHorizontal = true;
+ }
- for (int i = 0; i < width; i++)
- {
- for (int j = 0; j < height; j++)
- {
- Tile tile = Main.tile[x + i, y + j - height];
- tile.TileType = (ushort)type;
- tile.TileFrameX = (short)(i * 18 + startX);
- tile.TileFrameY = (short)(j * 18 + startY);
- tile.HasTile = true;
- }
- }
+ public static int GetFixedRandomNumber(int x, int y, int max = 1024)
+ {
+ Random random = new Random(SafeGetTile(Math.Abs(x), Math.Abs(y)).GetHashCode());
+ return random.Next(0, max);
+ }
+
+ public static int GetFixedRandomNumber(Point point, int max = 1024)
+ {
+ Random random = new Random(SafeGetTile(point).GetHashCode());
+ return random.Next(0, max);
+ }
+
+ public static int GetFixedRandomNumber(Tile tile, int max = 1024)
+ {
+ Random random = new Random(tile.GetHashCode());
+ return random.Next(0, max);
+ }
+
+ public static int GetFixedRandomNumber_SingleSeed(int seed, int max = 1024)
+ {
+ Random random = new Random(seed);
+ return random.Next(0, max);
}
public static bool AreaHasTile(int x, int y, int width, int height, Func prediction = null)
@@ -81,4 +109,78 @@ public static bool AreaHasTile(int x, int y, int width, int height, Func bars = new List();
+ Vector2 pos = drawPos + Main.screenPosition;
+ Vector2 offset0 = (new Vector2(0, 0) - origin).RotatedBy(rotation);
+ Vector2 offset1 = (new Vector2(frame.Width, 0) - origin).RotatedBy(rotation);
+ Vector2 offset2 = (new Vector2(0, frame.Height) - origin).RotatedBy(rotation);
+ Vector2 offset3 = (new Vector2(frame.Width, frame.Height) - origin).RotatedBy(rotation);
+
+ AddLightColorVertex(bars, pos + offset0, new Vector3(new Vector2(frame.X, frame.Y) / tex.Size(), 0));
+ AddLightColorVertex(bars, pos + offset1, new Vector3(new Vector2(frame.X + frame.Width, frame.Y) / tex.Size(), 0));
+ AddLightColorVertex(bars, pos + offset2, new Vector3(new Vector2(frame.X, frame.Y + frame.Height) / tex.Size(), 0));
+ AddLightColorVertex(bars, pos + offset3, new Vector3(new Vector2(frame.X + frame.Width, frame.Y + frame.Height) / tex.Size(), 0));
+ if (bars.Count > 2)
+ {
+ spriteBatch.GraphicsDevice.Textures[0] = tex;
+ spriteBatch.GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleStrip, bars.ToArray(), 0, bars.Count - 2);
+ }
+ }
+
+ public static void VertexDraw_Grid(Vector2 drawCenterPos, Rectangle frame, Vector2 origin, Texture2D tex, SpriteBatch spriteBatch, float rotation = 0, float alpha = 1f)
+ {
+ var drawPos = drawCenterPos;
+ List bars = new List();
+ Vector2 pos = drawPos + Main.screenPosition;
+ int xCount = frame.Width / 16;
+ int yCount = frame.Height / 16;
+ float unitX = frame.Width / (float)xCount;
+ float unitY = frame.Height / (float)yCount;
+ for (int x = 0; x < xCount; x++)
+ {
+ for (int y = 0; y < yCount; y++)
+ {
+ Vector2 offset0 = (new Vector2(x * unitX, y * unitY) - origin).RotatedBy(rotation);
+ Vector2 offset1 = (new Vector2((x + 1) * unitX, y * unitY) - origin).RotatedBy(rotation);
+ Vector2 offset2 = (new Vector2(x * unitX, (y + 1) * unitY) - origin).RotatedBy(rotation);
+ Vector2 offset3 = (new Vector2((x + 1) * unitX, (y + 1) * unitY) - origin).RotatedBy(rotation);
+
+ AddLightColorVertex(bars, pos + offset0, new Vector3(new Vector2(frame.X + x * unitX, frame.Y + y * unitY) / tex.Size(), 0), alpha);
+ AddLightColorVertex(bars, pos + offset1, new Vector3(new Vector2(frame.X + (x + 1) * unitX, frame.Y + y * unitY) / tex.Size(), 0), alpha);
+ AddLightColorVertex(bars, pos + offset2, new Vector3(new Vector2(frame.X + x * unitX, frame.Y + (y + 1) * unitY) / tex.Size(), 0), alpha);
+ AddLightColorVertex(bars, pos + offset3, new Vector3(new Vector2(frame.X + (x + 1) * unitX, frame.Y + (y + 1) * unitY) / tex.Size(), 0), alpha);
+ }
+ }
+
+ if (bars.Count > 2)
+ {
+ spriteBatch.GraphicsDevice.Textures[0] = tex;
+ spriteBatch.GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleStrip, bars.ToArray(), 0, bars.Count - 2);
+ }
+ }
+
+ public static void AddLightColorVertex(List bars, Vector2 worldPos, Vector3 coord, float alpha = 1f)
+ {
+ Color drawC = Lighting.GetColor(worldPos.ToTileCoordinates()) * alpha;
+ bars.Add(worldPos - Main.screenPosition, drawC, coord);
+ }
}
diff --git a/Sources/Everglow.Function/Utilities/TileUtils_Initialization.cs b/Sources/Everglow.Function/Utilities/TileUtils_Initialization.cs
new file mode 100644
index 000000000..33b5f55cd
--- /dev/null
+++ b/Sources/Everglow.Function/Utilities/TileUtils_Initialization.cs
@@ -0,0 +1,9 @@
+namespace Everglow.Commons.Utilities;
+
+public class TileUtilsInit : ModSystem
+{
+ public override void Load()
+ {
+ TileUtils.TotalInitialize();
+ }
+}
diff --git a/Sources/Modules/Yggdrasil/WorldGeneration/Noise_II_rgb.bmp b/Sources/Everglow.Function/Utilities/WorldGenLarge_rgb.bmp
similarity index 90%
rename from Sources/Modules/Yggdrasil/WorldGeneration/Noise_II_rgb.bmp
rename to Sources/Everglow.Function/Utilities/WorldGenLarge_rgb.bmp
index 04c2e2413..370b128fc 100644
Binary files a/Sources/Modules/Yggdrasil/WorldGeneration/Noise_II_rgb.bmp and b/Sources/Everglow.Function/Utilities/WorldGenLarge_rgb.bmp differ
diff --git a/Sources/Everglow.Function/Utilities/WorldGen_Noise_rgb.bmp b/Sources/Everglow.Function/Utilities/WorldGen_Noise_rgb.bmp
new file mode 100644
index 000000000..5a84375c6
Binary files /dev/null and b/Sources/Everglow.Function/Utilities/WorldGen_Noise_rgb.bmp differ
diff --git a/Sources/Everglow.Function/VFX/Effects/ColorDissolve.fx b/Sources/Everglow.Function/VFX/Effects/ColorDissolve.fx
new file mode 100644
index 000000000..862f5664e
--- /dev/null
+++ b/Sources/Everglow.Function/VFX/Effects/ColorDissolve.fx
@@ -0,0 +1,61 @@
+sampler2D uImage0 : register(s0);
+texture2D uDissolveNoise;
+sampler2D uDissolveNoiseTex = sampler_state
+{
+ Texture = ;
+ MinFilter = Linear;
+ MagFilter = Linear;
+ AddressU = Wrap;
+ AddressV = Wrap;
+};
+float4x4 uTransform;
+
+struct VSInput
+{
+ float2 Pos : POSITION0;
+ float4 Color : COLOR0;
+ float3 Texcoord : TEXCOORD0;
+};
+
+struct PSInput
+{
+ float4 Pos : SV_POSITION;
+ float4 Color : COLOR0;
+ float3 Texcoord : TEXCOORD0;
+};
+
+PSInput VertexShaderFunction(VSInput input)
+{
+ PSInput output;
+ output.Color = input.Color;
+ output.Texcoord = input.Texcoord;
+ output.Pos = mul(float4(input.Pos, 0, 1), uTransform);
+ return output;
+}
+
+float4 PixelShaderFunction(PSInput input) : COLOR0
+{
+ float4 tex = tex2D(uImage0, input.Texcoord.xy);
+ float4 heat = tex2D(uDissolveNoiseTex, input.Texcoord.xy);
+ if (!any(tex))
+ {
+ return float4(0, 0, 0, 0);
+ }
+ if (input.Texcoord.z * 1.2 < heat.r)
+ {
+ return float4(0, 0, 0, 0);
+ }
+ else if (input.Texcoord.z * 1.2 < heat.r + 0.2)
+ {
+ return lerp(tex, float4(0, 0, 0, 1), 0.5f) * input.Color;
+ }
+ return tex * input.Color;
+}
+technique Technique1
+{
+ pass Test
+ {
+ VertexShader = compile vs_3_0 VertexShaderFunction();
+ PixelShader = compile ps_3_0 PixelShaderFunction();
+ }
+}
diff --git a/Sources/Everglow.Function/VFX/Pipelines/ColorDissolvePipeline.cs b/Sources/Everglow.Function/VFX/Pipelines/ColorDissolvePipeline.cs
new file mode 100644
index 000000000..165c2d5f3
--- /dev/null
+++ b/Sources/Everglow.Function/VFX/Pipelines/ColorDissolvePipeline.cs
@@ -0,0 +1,27 @@
+namespace Everglow.Commons.VFX.Pipelines;
+
+public class ColorDissolvePipeline : Pipeline
+{
+ public override void Load()
+ {
+ effect = ModAsset.ColorDissolve;
+ effect.Value.Parameters["uDissolveNoise"].SetValue(ModAsset.Noise_flame_0.Value);
+ }
+
+ public override void BeginRender()
+ {
+ var effect = this.effect.Value;
+ var projection = Matrix.CreateOrthographicOffCenter(0, Main.screenWidth, Main.screenHeight, 0, 0, 1);
+ var model = Matrix.CreateTranslation(new Vector3(-Main.screenPosition, 0)) * Main.GameViewMatrix.TransformationMatrix;
+ effect.Parameters["uTransform"].SetValue(model * projection);
+
+ Main.graphics.GraphicsDevice.SamplerStates[0] = SamplerState.PointWrap;
+ Ins.Batch.Begin(BlendState.AlphaBlend, DepthStencilState.None, SamplerState.PointWrap, RasterizerState.CullNone);
+ effect.CurrentTechnique.Passes[0].Apply();
+ }
+
+ public override void EndRender()
+ {
+ Ins.Batch.End();
+ }
+}
diff --git a/Sources/Everglow.Function/VFX/Scene/BackgroundVFX.cs b/Sources/Everglow.Function/VFX/Scene/BackgroundVFX.cs
deleted file mode 100644
index 6e75b707b..000000000
--- a/Sources/Everglow.Function/VFX/Scene/BackgroundVFX.cs
+++ /dev/null
@@ -1,114 +0,0 @@
-using Everglow.Commons.Enums;
-using Everglow.Commons.Vertex;
-using Everglow.Commons.VFX.Pipelines;
-
-namespace Everglow.Commons.VFX.Scene;
-
-[Pipeline(typeof(WCSPipeline))]
-public abstract class BackgroundVFX : Visual
-{
- public override CodeLayer DrawLayer => CodeLayer.PostDrawBG;
-
- public Vector2 position;
- public Texture2D texture;
- public Point originTile;
- public int originType;
- public int direction = 1;
-
- public override void Update()
- {
- if (originTile.X > 0 && originTile.X < Main.maxTilesX)
- {
- if (originTile.Y > 0 && originTile.Y < Main.maxTilesY)
- {
- Tile tile = Main.tile[originTile.X, originTile.Y];
- if (tile != null)
- {
- if (TileLoader.GetTile(tile.TileType) is ISceneTile)
- {
- if (tile.TileType == originType)
- {
- if (!tile.HasTile)
- {
- Active = false;
- SceneVFXSystem.TilePointHasScene[(originTile.X, originTile.Y)] = false;
- return;
- }
- }
- else
- {
- Active = false;
- SceneVFXSystem.TilePointHasScene[(originTile.X, originTile.Y)] = false;
- return;
- }
- }
- else
- {
- Active = false;
- SceneVFXSystem.TilePointHasScene[(originTile.X, originTile.Y)] = false;
- return;
- }
- }
- else
- {
- Active = false;
- SceneVFXSystem.TilePointHasScene[(originTile.X, originTile.Y)] = false;
- return;
- }
- }
- else
- {
- Active = false;
- SceneVFXSystem.TilePointHasScene[(originTile.X, originTile.Y)] = false;
- return;
- }
- }
- else
- {
- Active = false;
- SceneVFXSystem.TilePointHasScene[(originTile.X, originTile.Y)] = false;
- return;
- }
- Vector2 checkPos = position;
- if (VFXManager.InScreen(checkPos, 500))
- {
- Visible = true;
- }
- else
- {
- Active = false;
- SceneVFXSystem.TilePointHasScene[(originTile.X, originTile.Y)] = false;
- return;
- }
- }
-
- public override void Draw()
- {
- Color lightColor0 = Lighting.GetColor((int)position.X / 16, (int)position.Y / 16);
- Color lightColor1 = Lighting.GetColor((int)(position.X + texture.Width) / 16, (int)position.Y / 16);
- Color lightColor2 = Lighting.GetColor((int)position.X / 16, (int)(position.Y + texture.Height) / 16);
- Color lightColor3 = Lighting.GetColor((int)(position.X + texture.Width) / 16, (int)(position.Y + texture.Height) / 16);
-
- Ins.Batch.BindTexture(texture);
- List bars = new List()
- {
- new Vertex2D(position, lightColor0, new Vector3(0, 0, 0)),
- new Vertex2D(position + new Vector2(texture.Width, 0), lightColor1, new Vector3(1, 0, 0)),
-
- new Vertex2D(position + new Vector2(0, texture.Height), lightColor2, new Vector3(0, 1, 0)),
- new Vertex2D(position + new Vector2(texture.Width, texture.Height), lightColor3, new Vector3(1, 1, 0)),
- };
- if (direction < 0)
- {
- bars = new List()
- {
- new Vertex2D(position, lightColor0, new Vector3(1, 0, 0)),
- new Vertex2D(position + new Vector2(texture.Width, 0), lightColor1, new Vector3(0, 0, 0)),
-
- new Vertex2D(position + new Vector2(0, texture.Height), lightColor2, new Vector3(1, 1, 0)),
- new Vertex2D(position + new Vector2(texture.Width, texture.Height), lightColor3, new Vector3(0, 1, 0)),
- };
- }
- Ins.Batch.Draw(bars, PrimitiveType.TriangleStrip);
- }
-}
diff --git a/Sources/Everglow.Function/VFX/Scene/FlagLikeVFX.cs b/Sources/Everglow.Function/VFX/Scene/FlagLikeVFX.cs
new file mode 100644
index 000000000..665467f53
--- /dev/null
+++ b/Sources/Everglow.Function/VFX/Scene/FlagLikeVFX.cs
@@ -0,0 +1,162 @@
+using Everglow.Commons.Enums;
+using Everglow.Commons.Utilities;
+using Everglow.Commons.Vertex;
+using Everglow.Commons.VFX.Pipelines;
+
+namespace Everglow.Commons.VFX.Scene;
+
+///
+/// Texture must sized in any times of 16, such as 32x48, 16x16, 48x64...
+///
+[Pipeline(typeof(WCSPipeline))]
+public class FlagLikeVFX : TileVFX
+{
+ public override CodeLayer DrawLayer => CodeLayer.PostDrawPlayers;
+
+ public Vector2[,] Meshgrid;
+
+ public Vector2 AnchorOffset = Vector2.zeroVector;
+
+ public bool Flip_H = false;
+
+ ///
+ /// This associate with the distort magnitude in wind push.
+ ///
+ public float Hardness = 1f;
+
+ public void GenerateMeshgrid()
+ {
+ int width = Texture.Width / 16;
+ width += 1;
+ int height = Texture.Height / 16;
+ height += 1;
+ Meshgrid = new Vector2[width, height];
+ for (int x = 0; x < width; x++)
+ {
+ for (int y = 0; y < height; y++)
+ {
+ Meshgrid[x, y] = new Vector2(x, y) * 16 + OriginTilePos.ToWorldCoordinates() + AnchorOffset;
+ }
+ }
+ }
+
+ public override void Update()
+ {
+ if (Meshgrid == null || Meshgrid == default)
+ {
+ GenerateMeshgrid();
+ }
+ for (int x = 0; x < Meshgrid.GetLength(0); x++)
+ {
+ for (int y = 0; y < Meshgrid.GetLength(1); y++)
+ {
+ Vector2 origPos = new Vector2(x, y) * 16 + OriginTilePos.ToWorldCoordinates() + AnchorOffset;
+ if (y > 0)
+ {
+ origPos.X = Meshgrid[x, y - 1].X;
+ Meshgrid[x, y].Y += MathF.Pow(Meshgrid.GetLength(1) - y, 2) * 0.006f;
+ }
+ Meshgrid[x, y] += GetWindPush(Meshgrid[x, y].X, Meshgrid[x, y].Y, Hardness);
+ Meshgrid[x, y] += (origPos - Meshgrid[x, y]) * 0.2f;
+
+ if (y < Meshgrid.GetLength(1) - 1)
+ {
+ PushFrom(ref origPos, ref Meshgrid[x, y + 1]);
+ }
+ if (y > 0)
+ {
+ PushFrom(ref origPos, ref Meshgrid[x, y - 1]);
+ }
+ if (x < Meshgrid.GetLength(0) - 1)
+ {
+ PushFrom(ref origPos, ref Meshgrid[x + 1, y]);
+ }
+ if (x > 0)
+ {
+ PushFrom(ref origPos, ref Meshgrid[x - 1, y]);
+ }
+ }
+ }
+ base.Update();
+ }
+
+ public void PushFrom(ref Vector2 origPosition, ref Vector2 targetPos)
+ {
+ Vector2 totarget = targetPos - origPosition;
+ Vector2 force = totarget.NormalizeSafe() * (totarget.Length() - 16) * 1f;
+ origPosition += force;
+ targetPos -= force;
+ }
+
+ public override void Draw()
+ {
+ if (Meshgrid == null || Meshgrid == default)
+ {
+ GenerateMeshgrid();
+ }
+ List bars = new List();
+ for (int x = 0; x < Meshgrid.GetLength(0) - 1; x++)
+ {
+ for (int y = 0; y < Meshgrid.GetLength(1) - 1; y++)
+ {
+ AddVertex(bars, x, y);
+ AddVertex(bars, x + 1, y);
+ AddVertex(bars, x, y + 1);
+
+ AddVertex(bars, x, y + 1);
+ AddVertex(bars, x + 1, y);
+ AddVertex(bars, x + 1, y + 1);
+ }
+ }
+ Ins.Batch.Draw(Texture, bars, PrimitiveType.TriangleList);
+ }
+
+ public void AddVertex(List bars, int xIndex, int yIndex)
+ {
+ Vector2 position = Meshgrid[xIndex, yIndex];
+ Vector2 texCoord = new Vector2(xIndex, yIndex) / Texture.Size() * 16;
+ if (Flip_H)
+ {
+ texCoord.X = 1 - texCoord.X;
+ }
+ bars.Add(position, Lighting.GetColor(position.ToTileCoordinates()), new Vector3(texCoord, 0));
+ }
+
+ public static Vector2 GetWindPush(Vector2 pos, float hardness)
+ {
+ return GetWindPush(pos.X, pos.Y, hardness);
+ }
+
+ public static Vector2 GetWindPush(float x, float y, float hardness)
+ {
+ float noise = 0;
+ float timeValue = (float)Main.time * 0.08f;
+
+ for (int i = 0; i < 8; i++)
+ {
+ noise += MathF.Sin((timeValue + x * 0.15f + i) * MathF.Pow(2, i)) * MathF.Pow(2, -i);
+ }
+ for (int j = 0; j < 8; j++)
+ {
+ noise += MathF.Sin((timeValue + y * 0.15f) + j * MathF.Pow(2, j)) * MathF.Pow(2, -j);
+ }
+ float pushX = noise * 1f * Main.windSpeedCurrent + Main.windSpeedCurrent * 4f;
+ if (Main.tile[new Vector2(x, y).ToTileCoordinates()].WallType > WallID.None)
+ {
+ pushX = 0f;
+ }
+ Vector2 addVel = Vector2.zeroVector;
+ foreach (var player in Main.player)
+ {
+ if (player is not null && player.active)
+ {
+ if (player.Hitbox.Contains(new Point((int)x, (int)y)))
+ {
+ addVel += player.velocity * 0.6f;
+ }
+ }
+ }
+
+ return (new Vector2(pushX, 0) + addVel) * hardness;
+ }
+}
diff --git a/Sources/Everglow.Function/VFX/Scene/ForegroundVFX.cs b/Sources/Everglow.Function/VFX/Scene/ForegroundVFX.cs
deleted file mode 100644
index 36c411703..000000000
--- a/Sources/Everglow.Function/VFX/Scene/ForegroundVFX.cs
+++ /dev/null
@@ -1,119 +0,0 @@
-using Everglow.Commons.Enums;
-using Everglow.Commons.Vertex;
-using Everglow.Commons.VFX.Pipelines;
-
-namespace Everglow.Commons.VFX.Scene;
-
-[Pipeline(typeof(WCSPipeline))]
-public abstract class ForegroundVFX : Visual
-{
- public override CodeLayer DrawLayer => CodeLayer.PostDrawPlayers;
-
- public Vector2 position;
- public Texture2D texture;
- public Point originTile;
- public int originType;
- public int direction = 1;
- public int OutScreenDistanceMax = 500;
-
- public override void OnSpawn()
- {
- }
-
- public override void Update()
- {
- if (originTile.X > 0 && originTile.X < Main.maxTilesX)
- {
- if (originTile.Y > 0 && originTile.Y < Main.maxTilesY)
- {
- Tile tile = Main.tile[originTile.X, originTile.Y];
- if (tile != null)
- {
- if (TileLoader.GetTile(tile.TileType) is ISceneTile)
- {
- if (tile.TileType == originType)
- {
- if (!tile.HasTile)
- {
- Active = false;
- SceneVFXSystem.TilePointHasScene[(originTile.X, originTile.Y)] = false;
- return;
- }
- }
- else
- {
- Active = false;
- SceneVFXSystem.TilePointHasScene[(originTile.X, originTile.Y)] = false;
- return;
- }
- }
- else
- {
- Active = false;
- SceneVFXSystem.TilePointHasScene[(originTile.X, originTile.Y)] = false;
- return;
- }
- }
- else
- {
- Active = false;
- SceneVFXSystem.TilePointHasScene[(originTile.X, originTile.Y)] = false;
- return;
- }
- }
- else
- {
- Active = false;
- SceneVFXSystem.TilePointHasScene[(originTile.X, originTile.Y)] = false;
- return;
- }
- }
- else
- {
- Active = false;
- SceneVFXSystem.TilePointHasScene[(originTile.X, originTile.Y)] = false;
- return;
- }
- Vector2 checkPos = position;
- if (VFXManager.InScreen(checkPos, OutScreenDistanceMax))
- {
- Visible = true;
- }
- else
- {
- Active = false;
- SceneVFXSystem.TilePointHasScene[(originTile.X, originTile.Y)] = false;
- return;
- }
- }
-
- public override void Draw()
- {
- Color lightColor0 = Lighting.GetColor((int)position.X / 16, (int)position.Y / 16);
- Color lightColor1 = Lighting.GetColor((int)(position.X + texture.Width) / 16, (int)position.Y / 16);
- Color lightColor2 = Lighting.GetColor((int)position.X / 16, (int)(position.Y + texture.Height) / 16);
- Color lightColor3 = Lighting.GetColor((int)(position.X + texture.Width) / 16, (int)(position.Y + texture.Height) / 16);
-
- Ins.Batch.BindTexture(texture);
- List bars = new List()
- {
- new Vertex2D(position, lightColor0, new Vector3(0, 0, 0)),
- new Vertex2D(position + new Vector2(texture.Width, 0), lightColor1, new Vector3(1, 0, 0)),
-
- new Vertex2D(position + new Vector2(0, texture.Height), lightColor2, new Vector3(0, 1, 0)),
- new Vertex2D(position + new Vector2(texture.Width, texture.Height), lightColor3, new Vector3(1, 1, 0)),
- };
- if (direction < 0)
- {
- bars = new List()
- {
- new Vertex2D(position, lightColor0, new Vector3(1, 0, 0)),
- new Vertex2D(position + new Vector2(texture.Width, 0), lightColor1, new Vector3(0, 0, 0)),
-
- new Vertex2D(position + new Vector2(0, texture.Height), lightColor2, new Vector3(1, 1, 0)),
- new Vertex2D(position + new Vector2(texture.Width, texture.Height), lightColor3, new Vector3(0, 1, 0)),
- };
- }
- Ins.Batch.Draw(bars, PrimitiveType.TriangleStrip);
- }
-}
diff --git a/Sources/Everglow.Function/VFX/Scene/SceneUtils.cs b/Sources/Everglow.Function/VFX/Scene/SceneUtils.cs
new file mode 100644
index 000000000..028dddd1a
--- /dev/null
+++ b/Sources/Everglow.Function/VFX/Scene/SceneUtils.cs
@@ -0,0 +1,126 @@
+using Everglow.Commons.Vertex;
+
+namespace Everglow.Commons.VFX.Scene;
+
+public class SceneUtils
+{
+ ///
+ /// Fill draw vertices that cover a tile.(TriangleList)
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void DrawTileCover(int i, int j, Texture2D texture, float startCoordX, float startCoordY, List bars, bool flipH, float colorFactors)
+ {
+ Vector2 drawPos0 = new Point(i, j).ToWorldCoordinates() - new Vector2(8);
+ Vector2 drawPos1 = drawPos0 + new Vector2(16, 0);
+ Vector2 drawPos2 = drawPos0 + new Vector2(0, 16);
+ Vector2 drawPos3 = drawPos0 + new Vector2(16, 16);
+
+ Color light0 = Lighting.GetColor(drawPos0.ToTileCoordinates()) * colorFactors;
+ Color light1 = Lighting.GetColor(drawPos1.ToTileCoordinates()) * colorFactors;
+ Color light2 = Lighting.GetColor(drawPos2.ToTileCoordinates()) * colorFactors;
+ Color light3 = Lighting.GetColor(drawPos3.ToTileCoordinates()) * colorFactors;
+
+ Vector2 size = new Vector2(16) / texture.Size();
+
+ float coordX0 = startCoordX;
+ float coordX1 = startCoordX + size.X;
+ if (flipH)
+ {
+ (coordX0, coordX1) = (coordX1, coordX0);
+ }
+
+ bars.Add(drawPos0, light0, new Vector3(coordX0, startCoordY, 0));
+ bars.Add(drawPos1, light1, new Vector3(coordX1, startCoordY, 0));
+ bars.Add(drawPos3, light3, new Vector3(coordX1, startCoordY + size.Y, 0));
+
+ bars.Add(drawPos0, light0, new Vector3(coordX0, startCoordY, 0));
+ bars.Add(drawPos3, light3, new Vector3(coordX1, startCoordY + size.Y, 0));
+ bars.Add(drawPos2, light2, new Vector3(coordX0, startCoordY + size.Y, 0));
+ }
+
+ ///
+ /// Make sure the width and the height of the texture are the multiples of 16.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void DrawMultiSceneTowardBottom(int i, int j, Texture2D texture, List bars, bool flipH, float colorFactors = 1)
+ {
+ for (int x = 0; x < texture.Width; x += 16)
+ {
+ for (int y = 0; y < texture.Height; y += 16)
+ {
+ if (flipH)
+ {
+ DrawTileCover(i - x / 16, j + y / 16, texture, x / (float)texture.Width, y / (float)texture.Height, bars, flipH, colorFactors);
+ }
+ else
+ {
+ DrawTileCover(i + x / 16, j + y / 16, texture, x / (float)texture.Width, y / (float)texture.Height, bars, flipH, colorFactors);
+ }
+ }
+ }
+ }
+
+ //public static void DrawHangingFlagLike(Vector2 anchorPos, Texture2D texture, List bars, bool flipH, float colorFactors = 1)
+ //{
+ // Vector2 halfSize = new Vector2(texture.Width * 0.5f, 0);
+ // for (int x = 0; x < texture.Width; x += 16)
+ // {
+ // for (int y = 0; y < texture.Height; y += 16)
+ // {
+ // if (x > texture.Width)
+ // {
+ // x = texture.Width;
+ // }
+ // if (y > texture.Height)
+ // {
+ // y = texture.Height;
+ // }
+ // DrawFlagLikeCover(anchorPos + new Vector2(x, y) - halfSize, texture, x / (float)texture.Width, y / (float)texture.Height, bars, false, colorFactors);
+ // }
+ // }
+ //}
+
+ //public static void DrawFlagLikeCover(Vector2 worldPos, Texture2D texture, float startCoordX, float startCoordY, List bars, bool flipH, float colorFactors)
+ //{
+ // Vector2 drawPos0 = worldPos - new Vector2(8);
+ // Vector2 drawPos1 = drawPos0 + new Vector2(16, 0);
+ // Vector2 drawPos2 = drawPos0 + new Vector2(0, 16);
+ // Vector2 drawPos3 = drawPos0 + new Vector2(16, 16);
+
+ // Vector2 size = new Vector2(16) / texture.Size();
+ // float weight0 = texture.Size().Y * (1 - startCoordY) / 16f;
+ // float weight1 = texture.Size().Y * (1 - (startCoordY + size.Y)) / 16f;
+ // drawPos0 += GetWindPushBalance(drawPos0, weight0);
+ // drawPos1 += GetWindPushBalance(drawPos1, weight0);
+ // drawPos2 += GetWindPushBalance(drawPos2, weight1);
+ // drawPos3 += GetWindPushBalance(drawPos3, weight1);
+
+ // Color light0 = Lighting.GetColor(drawPos0.ToTileCoordinates()) * colorFactors;
+ // Color light1 = Lighting.GetColor(drawPos1.ToTileCoordinates()) * colorFactors;
+ // Color light2 = Lighting.GetColor(drawPos2.ToTileCoordinates()) * colorFactors;
+ // Color light3 = Lighting.GetColor(drawPos3.ToTileCoordinates()) * colorFactors;
+
+ // float coordX0 = startCoordX;
+ // float coordX1 = startCoordX + size.X;
+ // if (flipH)
+ // {
+ // (coordX0, coordX1) = (coordX1, coordX0);
+ // }
+
+ // bars.Add(drawPos0, light0, new Vector3(coordX0, startCoordY, 0));
+ // bars.Add(drawPos1, light1, new Vector3(coordX1, startCoordY, 0));
+ // bars.Add(drawPos3, light3, new Vector3(coordX1, startCoordY + size.Y, 0));
+
+ // bars.Add(drawPos0, light0, new Vector3(coordX0, startCoordY, 0));
+ // bars.Add(drawPos3, light3, new Vector3(coordX1, startCoordY + size.Y, 0));
+ // bars.Add(drawPos2, light2, new Vector3(coordX0, startCoordY + size.Y, 0));
+ //}
+}
diff --git a/Sources/Everglow.Function/VFX/Scene/TileVFX.cs b/Sources/Everglow.Function/VFX/Scene/TileVFX.cs
new file mode 100644
index 000000000..008e86864
--- /dev/null
+++ b/Sources/Everglow.Function/VFX/Scene/TileVFX.cs
@@ -0,0 +1,114 @@
+using Everglow.Commons.Enums;
+using Everglow.Commons.Vertex;
+using Everglow.Commons.VFX.Pipelines;
+
+namespace Everglow.Commons.VFX.Scene;
+
+[Pipeline(typeof(WCSPipeline))]
+public abstract class TileVFX : Visual
+{
+ public override CodeLayer DrawLayer => CodeLayer.PostDrawPlayers;
+
+ public Vector2 Position;
+ public Texture2D Texture;
+ public Point OriginTilePos;
+ public int OriginTileType;
+ public int Direction = 1;
+ public float MaxDiatanceOutOfScreen = 500;
+
+ public override void Update()
+ {
+ if (OriginTilePos.X > 0 && OriginTilePos.X < Main.maxTilesX)
+ {
+ if (OriginTilePos.Y > 0 && OriginTilePos.Y < Main.maxTilesY)
+ {
+ Tile tile = Main.tile[OriginTilePos.X, OriginTilePos.Y];
+ if (tile != null)
+ {
+ if (TileLoader.GetTile(tile.TileType) is ISceneTile)
+ {
+ if (tile.TileType == OriginTileType)
+ {
+ if (!tile.HasTile)
+ {
+ Active = false;
+ SceneVFXSystem.TilePointHasScene[(OriginTilePos.X, OriginTilePos.Y)] = false;
+ return;
+ }
+ }
+ else
+ {
+ Active = false;
+ SceneVFXSystem.TilePointHasScene[(OriginTilePos.X, OriginTilePos.Y)] = false;
+ return;
+ }
+ }
+ else
+ {
+ Active = false;
+ SceneVFXSystem.TilePointHasScene[(OriginTilePos.X, OriginTilePos.Y)] = false;
+ return;
+ }
+ }
+ else
+ {
+ Active = false;
+ SceneVFXSystem.TilePointHasScene[(OriginTilePos.X, OriginTilePos.Y)] = false;
+ return;
+ }
+ }
+ else
+ {
+ Active = false;
+ SceneVFXSystem.TilePointHasScene[(OriginTilePos.X, OriginTilePos.Y)] = false;
+ return;
+ }
+ }
+ else
+ {
+ Active = false;
+ SceneVFXSystem.TilePointHasScene[(OriginTilePos.X, OriginTilePos.Y)] = false;
+ return;
+ }
+ Vector2 checkPos = Position;
+ if (VFXManager.InScreen(checkPos, MaxDiatanceOutOfScreen))
+ {
+ Visible = true;
+ }
+ else
+ {
+ Active = false;
+ SceneVFXSystem.TilePointHasScene[(OriginTilePos.X, OriginTilePos.Y)] = false;
+ return;
+ }
+ }
+
+ public override void Draw()
+ {
+ Color lightColor0 = Lighting.GetColor((int)Position.X / 16, (int)Position.Y / 16);
+ Color lightColor1 = Lighting.GetColor((int)(Position.X + Texture.Width) / 16, (int)Position.Y / 16);
+ Color lightColor2 = Lighting.GetColor((int)Position.X / 16, (int)(Position.Y + Texture.Height) / 16);
+ Color lightColor3 = Lighting.GetColor((int)(Position.X + Texture.Width) / 16, (int)(Position.Y + Texture.Height) / 16);
+
+ List bars = new List()
+ {
+ new Vertex2D(Position, lightColor0, new Vector3(0, 0, 0)),
+ new Vertex2D(Position + new Vector2(Texture.Width, 0), lightColor1, new Vector3(1, 0, 0)),
+
+ new Vertex2D(Position + new Vector2(0, Texture.Height), lightColor2, new Vector3(0, 1, 0)),
+ new Vertex2D(Position + new Vector2(Texture.Width, Texture.Height), lightColor3, new Vector3(1, 1, 0)),
+ };
+ if (Direction < 0)
+ {
+ bars = new List()
+ {
+ new Vertex2D(Position, lightColor0, new Vector3(1, 0, 0)),
+ new Vertex2D(Position + new Vector2(Texture.Width, 0), lightColor1, new Vector3(0, 0, 0)),
+
+ new Vertex2D(Position + new Vector2(0, Texture.Height), lightColor2, new Vector3(1, 1, 0)),
+ new Vertex2D(Position + new Vector2(Texture.Width, Texture.Height), lightColor3, new Vector3(0, 1, 0)),
+ };
+ }
+ Ins.Batch.Draw(Texture, bars, PrimitiveType.TriangleStrip);
+ }
+}
diff --git a/Sources/Everglow.Function/VFX/Scene/Tile_MirrorFaceVFX.cs b/Sources/Everglow.Function/VFX/Scene/Tile_MirrorFaceVFX.cs
index 00aa57b81..c5827ec11 100644
--- a/Sources/Everglow.Function/VFX/Scene/Tile_MirrorFaceVFX.cs
+++ b/Sources/Everglow.Function/VFX/Scene/Tile_MirrorFaceVFX.cs
@@ -9,10 +9,10 @@ public abstract class Tile_MirrorFaceVFX : Visual
{
public override CodeLayer DrawLayer => CodeLayer.PostDrawProjectiles;
- public Vector2 position;
- public Texture2D texture;
- public Point originTile;
- public int originType;
+ public Vector2 Position;
+ public Texture2D Texture;
+ public Point OriginTilePos;
+ public int OriginTileType;
public float DepthZ = -50;
public override void OnSpawn()
@@ -21,76 +21,76 @@ public override void OnSpawn()
public override void Update()
{
- if (originTile.X > 0 && originTile.X < Main.maxTilesX)
+ if (OriginTilePos.X > 0 && OriginTilePos.X < Main.maxTilesX)
{
- if (originTile.Y > 0 && originTile.Y < Main.maxTilesY)
+ if (OriginTilePos.Y > 0 && OriginTilePos.Y < Main.maxTilesY)
{
- Tile tile = Main.tile[originTile.X, originTile.Y];
+ Tile tile = Main.tile[OriginTilePos.X, OriginTilePos.Y];
if (tile != null)
{
if (TileLoader.GetTile(tile.TileType) is ISceneTile)
{
- if (tile.TileType == originType)
+ if (tile.TileType == OriginTileType)
{
if (!tile.HasTile)
{
Active = false;
- SceneVFXSystem.TilePointHasScene[(originTile.X, originTile.Y)] = false;
+ SceneVFXSystem.TilePointHasScene[(OriginTilePos.X, OriginTilePos.Y)] = false;
}
}
else
{
Active = false;
- SceneVFXSystem.TilePointHasScene[(originTile.X, originTile.Y)] = false;
+ SceneVFXSystem.TilePointHasScene[(OriginTilePos.X, OriginTilePos.Y)] = false;
}
}
else
{
Active = false;
- SceneVFXSystem.TilePointHasScene[(originTile.X, originTile.Y)] = false;
+ SceneVFXSystem.TilePointHasScene[(OriginTilePos.X, OriginTilePos.Y)] = false;
}
}
else
{
Active = false;
- SceneVFXSystem.TilePointHasScene[(originTile.X, originTile.Y)] = false;
+ SceneVFXSystem.TilePointHasScene[(OriginTilePos.X, OriginTilePos.Y)] = false;
}
}
else
{
Active = false;
- SceneVFXSystem.TilePointHasScene[(originTile.X, originTile.Y)] = false;
+ SceneVFXSystem.TilePointHasScene[(OriginTilePos.X, OriginTilePos.Y)] = false;
}
}
else
{
Active = false;
- SceneVFXSystem.TilePointHasScene[(originTile.X, originTile.Y)] = false;
+ SceneVFXSystem.TilePointHasScene[(OriginTilePos.X, OriginTilePos.Y)] = false;
}
- Vector2 checkPos = position + texture.Size() / 2;
- if (VFXManager.InScreen(checkPos, Math.Max(texture.Width, texture.Height + 200)))
+ Vector2 checkPos = Position + Texture.Size() / 2;
+ if (VFXManager.InScreen(checkPos, Math.Max(Texture.Width, Texture.Height + 200)))
{
Visible = true;
}
else
{
Active = false;
- SceneVFXSystem.TilePointHasScene[(originTile.X, originTile.Y)] = false;
+ SceneVFXSystem.TilePointHasScene[(OriginTilePos.X, OriginTilePos.Y)] = false;
}
}
public override void Draw()
{
Color color = Color.White;
- Main.graphics.GraphicsDevice.Textures[1] = texture;
+ Main.graphics.GraphicsDevice.Textures[1] = Texture;
float z = DepthZ;
List bars = new List()
{
- new MirrorFaceVertex(new Vector3(position, z), color, new Vector3(0, 0, 0)),
- new MirrorFaceVertex(new Vector3(position + new Vector2(texture.Width, 0), z), color, new Vector3(1, 0, 0)),
+ new MirrorFaceVertex(new Vector3(Position, z), color, new Vector3(0, 0, 0)),
+ new MirrorFaceVertex(new Vector3(Position + new Vector2(Texture.Width, 0), z), color, new Vector3(1, 0, 0)),
- new MirrorFaceVertex(new Vector3(position + new Vector2(0, texture.Height), z), color, new Vector3(0, 1, 0)),
- new MirrorFaceVertex(new Vector3(position + new Vector2(texture.Width, texture.Height), z), color, new Vector3(1, 1, 0)),
+ new MirrorFaceVertex(new Vector3(Position + new Vector2(0, Texture.Height), z), color, new Vector3(0, 1, 0)),
+ new MirrorFaceVertex(new Vector3(Position + new Vector2(Texture.Width, Texture.Height), z), color, new Vector3(1, 1, 0)),
};
Main.graphics.GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleStrip, bars.ToArray(), 0, bars.Count - 2);
}
diff --git a/Sources/Everglow.UnitTests/Everglow.UnitTests.csproj b/Sources/Everglow.UnitTests/Everglow.UnitTests.csproj
index 6cc1bcb03..793b67954 100644
--- a/Sources/Everglow.UnitTests/Everglow.UnitTests.csproj
+++ b/Sources/Everglow.UnitTests/Everglow.UnitTests.csproj
@@ -31,6 +31,8 @@
+
+
diff --git a/Sources/Everglow.UnitTests/Modules/Yggdrasil/Common/YggdrasilPlayerTests.cs b/Sources/Everglow.UnitTests/Modules/Yggdrasil/Common/YggdrasilPlayerTests.cs
new file mode 100644
index 000000000..601cfa4e6
--- /dev/null
+++ b/Sources/Everglow.UnitTests/Modules/Yggdrasil/Common/YggdrasilPlayerTests.cs
@@ -0,0 +1,92 @@
+using System.Reflection;
+using Everglow.Yggdrasil;
+using Everglow.Yggdrasil.Common;
+using SubworldLibrary;
+using Terraria;
+using Terraria.ModLoader;
+
+namespace Everglow.UnitTests.Modules.Yggdrasil.Common;
+
+[TestClass]
+[DoNotParallelize]
+public class YggdrasilPlayerTests
+{
+ private static readonly FieldInfo CurrentSubworldField = typeof(SubworldSystem).GetField("current", BindingFlags.NonPublic | BindingFlags.Static)!;
+
+ private Subworld? originalSubworld;
+ private Player player = null!;
+ private YggdrasilPlayer modPlayer = null!;
+
+ [TestInitialize]
+ public void Initialize()
+ {
+ Program.SavePath = string.Empty;
+ originalSubworld = (Subworld?)CurrentSubworldField.GetValue(null);
+ CurrentSubworldField.SetValue(null, null);
+
+ player = new Player();
+ modPlayer = (YggdrasilPlayer)new YggdrasilPlayer().NewInstance(player);
+ }
+
+ [TestCleanup]
+ public void Cleanup()
+ {
+ CurrentSubworldField.SetValue(null, originalSubworld);
+ }
+
+ [TestMethod]
+ public void ModifyMaxStats_InYggdrasil_ReplacesVanillaGrowthAndAddsPermanentBoosts()
+ {
+ player.ConsumedLifeCrystals = 15;
+ player.ConsumedLifeFruit = 20;
+ player.ConsumedManaCrystals = 9;
+ SetPermanentLifeBoosts();
+ CurrentSubworldField.SetValue(null, new YggdrasilWorld());
+
+ modPlayer.ModifyMaxStats(out var health, out var mana);
+
+ Assert.AreEqual(-237f, health.Base);
+ Assert.AreEqual(-144f, mana.Base);
+ Assert.AreEqual(263, (int)health.ApplyTo(500f));
+ Assert.AreEqual(56, (int)mana.ApplyTo(200f));
+ }
+
+ [TestMethod]
+ public void ModifyMaxStats_OutsideYggdrasil_KeepsVanillaGrowthAndAddsPermanentBoosts()
+ {
+ player.ConsumedLifeCrystals = 15;
+ player.ConsumedLifeFruit = 20;
+ player.ConsumedManaCrystals = 9;
+ SetPermanentLifeBoosts();
+
+ modPlayer.ModifyMaxStats(out var health, out var mana);
+
+ Assert.AreEqual(83f, health.Base);
+ Assert.AreEqual(0f, mana.Base);
+ Assert.AreEqual(583, (int)health.ApplyTo(500f));
+ Assert.AreEqual(200, (int)mana.ApplyTo(200f));
+ }
+
+ [TestMethod]
+ public void ModifyMaxStats_ComposesAsBaseWithOtherModifiersRegardlessOfOrder()
+ {
+ player.ConsumedLifeCrystals = 1;
+ CurrentSubworldField.SetValue(null, new YggdrasilWorld());
+
+ modPlayer.ModifyMaxStats(out var health, out _);
+ var otherMod = new StatModifier(additive: 1.5f, multiplicative: 2f, flat: 7f, @base: 10f);
+ var yggdrasilFirst = health.CombineWith(otherMod);
+ var otherModFirst = otherMod.CombineWith(health);
+
+ Assert.AreEqual(yggdrasilFirst, otherModFirst);
+ Assert.AreEqual(349, (int)yggdrasilFirst.ApplyTo(120f));
+ }
+
+ private void SetPermanentLifeBoosts()
+ {
+ modPlayer.ConsumedAntiHeavenSicknessPill = 5;
+ modPlayer.ConsumedJadeGlazeFruit = 2;
+ modPlayer.ConsumedSquamousCore = 1;
+ modPlayer.ConsumedLampBorerHoney = 3;
+ }
+}
diff --git a/Sources/Everglow/Localization/en-US/Mods.Everglow.Biomes.hjson b/Sources/Everglow/Localization/en-US/Mods.Everglow.Biomes.hjson
index 93593950f..f83b10438 100644
--- a/Sources/Everglow/Localization/en-US/Mods.Everglow.Biomes.hjson
+++ b/Sources/Everglow/Localization/en-US/Mods.Everglow.Biomes.hjson
@@ -1,54 +1,54 @@
YggdrasilTownBiome: {
DisplayName: Yggdrasil Town
- TownNPCDialogueName: The Yggdrasil Town
+ TownNPCDialogueName: Yggdrasil Town
}
TuskBiome: {
- DisplayName: Tusk Biome
- TownNPCDialogueName: ""
+ DisplayName: Tusk Tableland
+ TownNPCDialogueName: the Tusk Tableland biome
}
TuskSurfaceBiome: {
- DisplayName: Tusk Surface Biome
- TownNPCDialogueName: ""
+ DisplayName: Surface Tusk Tuya
+ TownNPCDialogueName: the Surface Tusk Tableland biome
}
FireflyBiome: {
- DisplayName: Firefly Biome
- TownNPCDialogueName: ""
+ DisplayName: Everglowing Cocoon
+ TownNPCDialogueName: the Everglowing Cocoon
}
FurnaceAreaBiome: {
- DisplayName: Furnace Area Biome
- TownNPCDialogueName: ""
+ DisplayName: Yggdrasil Forge
+ TownNPCDialogueName: the Yggdrasil Forge
}
JellyBallHotbedBiome: {
- DisplayName: Jelly Ball Hotbed Biome
- TownNPCDialogueName: ""
+ DisplayName: Jellyball Hotbed
+ TownNPCDialogueName: the Jellyball Hotbed
}
LampWoodForest: {
- DisplayName: Lamp Wood Forest
- TownNPCDialogueName: ""
+ DisplayName: Lampwood Forest
+ TownNPCDialogueName: the Lampwood Forest biome
}
MidnightBayouBiome: {
- DisplayName: Midnight Bayou Biome
- TownNPCDialogueName: ""
+ DisplayName: Midnight Marsh
+ TownNPCDialogueName: the Midnight Marsh biome
}
TwilightForsetAndRelic: {
- DisplayName: Twilight Forset And Relic
- TownNPCDialogueName: ""
+ DisplayName: Twilight Forest
+ TownNPCDialogueName: the Twilight Forest biome
}
KelpCurtainBiome: {
- DisplayName: Kelp Curtain Biome
- TownNPCDialogueName: ""
+ DisplayName: Moss Mantle
+ TownNPCDialogueName: the Moss Mantle biome
}
HurricaneMazeBiome: {
- DisplayName: Hurricane Maze Biome
- TownNPCDialogueName: ""
+ DisplayName: Tempest Labyrinth
+ TownNPCDialogueName: the Tempest Labyrinth biome
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Biomes.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Biomes.hjson
index df9c0ba5a..afd6d5e18 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Biomes.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Biomes.hjson
@@ -4,51 +4,51 @@ YggdrasilTownBiome: {
}
TuskBiome: {
- DisplayName: Tusk Biome
- TownNPCDialogueName: ""
+ DisplayName: 颌骨å°åœ°
+ TownNPCDialogueName: 颌骨å°åœ°
}
TuskSurfaceBiome: {
- DisplayName: Tusk Surface Biome
- TownNPCDialogueName: ""
+ DisplayName: 颌骨å°åœ°åœ°é¢
+ TownNPCDialogueName: 颌骨å°åœ°åœ°é¢
}
FireflyBiome: {
- DisplayName: Firefly Biome
- TownNPCDialogueName: ""
+ DisplayName: æµè¤ä¹‹èŒ§
+ TownNPCDialogueName: æµè¤ä¹‹èŒ§
}
FurnaceAreaBiome: {
- DisplayName: Furnace Area Biome
- TownNPCDialogueName: ""
+ DisplayName: 天穹镇炉心区
+ TownNPCDialogueName: 天穹镇炉心区
}
JellyBallHotbedBiome: {
- DisplayName: Jelly Ball Hotbed Biome
- TownNPCDialogueName: ""
+ DisplayName: çƒå†»æ¸©åºŠ
+ TownNPCDialogueName: çƒå†»æ¸©åºŠ
}
LampWoodForest: {
- DisplayName: Lamp Wood Forest
- TownNPCDialogueName: ""
+ DisplayName: ç¯æœ¨æ£®æž—
+ TownNPCDialogueName: ç¯æœ¨æ£®æž—
}
MidnightBayouBiome: {
- DisplayName: Midnight Bayou Biome
- TownNPCDialogueName: ""
+ DisplayName: åˆå¤œæ²¼æ³½
+ TownNPCDialogueName: åˆå¤œæ²¼æ³½
}
TwilightForsetAndRelic: {
- DisplayName: Twilight Forset And Relic
- TownNPCDialogueName: ""
+ DisplayName: 暮光森林
+ TownNPCDialogueName: 暮光森林
}
KelpCurtainBiome: {
- DisplayName: Kelp Curtain Biome
- TownNPCDialogueName: ""
+ DisplayName: è‹è‹”帘幕
+ TownNPCDialogueName: è‹è‹”帘幕
}
HurricaneMazeBiome: {
- DisplayName: Hurricane Maze Biome
- TownNPCDialogueName: ""
+ DisplayName: 飓风迷宫
+ TownNPCDialogueName: 飓风迷宫
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Buffs.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Buffs.hjson
index 4e0663b73..f338a7dc2 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Buffs.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Buffs.hjson
@@ -1,983 +1,1460 @@
DevilHeartSetBuff: {
DisplayName: é”心过载
Description:
- '''
- åœæ¢è‡ªç„¶é”力å†ç”Ÿå¹¶é™ä½Žé˜²å¾¡
- ä½†èŽ·å¾—é”æ³•ä¼¤å®³ä¸Žæš´å‡»åŠ æˆï¼ŒåŒæ—¶å¢žåŠ å¬å”¤æ
- '''
+ '''
+ åœæ¢è‡ªç„¶é”力å†ç”Ÿå¹¶é™ä½Žé˜²å¾¡
+ ä½†èŽ·å¾—é”æ³•ä¼¤å®³ä¸Žæš´å‡»åŠ æˆï¼ŒåŒæ—¶å¢žåŠ å¬å”¤æ
+ '''
}
BloodSwordStrikeBuff: {
- DisplayName: Blood Sword Strike Buff
+ DisplayName: 汲血剑
Description: ""
}
LifeRotten: {
- DisplayName: Life Rotten
+ DisplayName: 生命è…化
Description: ""
}
BloodDrinking: {
- DisplayName: Blood Drinking
+ DisplayName: 茹毛饮血
Description: ""
}
OnElectric: {
- DisplayName: On Electric
+ DisplayName: 触电
Description: ""
}
StaminaEnergyBuff: {
- DisplayName: Stamina Energy Buff
- Description: ""
+ DisplayName: 能é‡é¥®æ–™
+ Description: "使用刺剑时体力更多"
}
StarCrack: {
- DisplayName: Star Crack
+ DisplayName: 裂星
Description: ""
}
AppleBuff: {
- DisplayName: Apple Buff
- Description: ""
+ DisplayName: 苹果
+ Description:
+ '''
+ å¢žåŠ 5%å‡ä¼¤!!!
+ 一天一苹果,医生远离我
+ '''
}
ApplePieBuff: {
- DisplayName: Apple Pie Buff
- Description: ""
+ DisplayName: 苹果派
+ Description:
+ '''
+ åŠ 5%å‡ä¼¤,1生命回å¤!!!
+ 一天一苹果,医生远离我,苹果派也行
+ '''
}
ApricotBuff: {
- DisplayName: Apricot Buff
- Description: ""
+ DisplayName: æ
+ Description:
+ '''
+ å¢žåŠ 4é”力å†ç”Ÿ!!!
+ æ¢æ¸´æ¶¦è‚º
+ '''
}
BaconBuff: {
- DisplayName: Bacon Buff
- Description: ""
+ DisplayName: åŸ¹æ ¹
+ Description:
+ '''
+ åŠ 2生命回å¤ï¼Œæ‰€å—冷系伤害é™ä½Ž
+ â€”â€”æ³•å›½äººéƒ½æ˜¯åŸ¹æ ¹
+ '''
}
BananaBuff: {
- DisplayName: Banana Buff
- Description: ""
+ DisplayName: 香蕉
+ Description:
+ '''
+ 5%䏿¶ˆè€—å¼¹è¯ï¼Œå¢žåŠ 5%机枪类æ¦å™¨è¿œç¨‹å°„速!!!
+ 低血压
+ '''
}
BananaSplitBuff: {
- DisplayName: Banana Split Buff
- Description: ""
+ DisplayName: 香蕉船
+ Description:
+ '''
+ 10%䏿¶ˆè€—å¼¹è¯ï¼Œå¢žåŠ 6%远程暴击!!!
+ 低血压
+ '''
}
BBQRibsBuff: {
- DisplayName: BBQRibs Buff
- Description: ""
+ DisplayName: 烧烤排骨
+ Description:
+ '''
+ å¢žåŠ 50最大生命值!!!
+ 滋阴补血
+ '''
}
BlackCurrantBuff: {
- DisplayName: Black Currant Buff
- Description: ""
+ DisplayName: é»‘åŠ ä»‘
+ Description:
+ '''
+ 获得夜视ã€å±é™©æ„ŸçŸ¥èƒ½åŠ›
+ 改善视力
+ '''
}
BloodOrangeBuff: {
- DisplayName: Blood Orange Buff
- Description: ""
+ DisplayName: 血橙
+ Description:
+ '''
+ å¢žåŠ 25最大生命值!!!
+ è¿™é‡Œä¸æ˜¯å´½é¥¿
+ '''
}
BowlofSoupBuff: {
- DisplayName: Bowlof Soup Buff
- Description: ""
+ DisplayName: é±¼è‡æ±¤
+ Description:
+ '''
+ å¢žåŠ 40最大é”力值,5%锿³•伤害
+ 补脑
+ '''
}
BunnyStewBuff: {
- DisplayName: Bunny Stew Buff
- Description: ""
+ DisplayName: 炖兔兔
+ Description:
+ '''
+ 自动跳跃,æå‡è·³è·ƒèƒ½åŠ›!!!ï¼
+ 没有任何兔å在制作过程ä¸å—到伤害
+ '''
}
BurgerBuff: {
- DisplayName: Burger Buff
- Description: ""
+ DisplayName: æ±‰å ¡
+ Description:
+ '''
+ å‡å°‘ç§»é€Ÿï¼Œå¢žåŠ é˜²å¾¡
+ çƒé‡ç‚¸å¼¹
+ '''
}
CherryBuff: {
- DisplayName: Cherry Buff
- Description: ""
+ DisplayName: 樱桃
+ Description:
+ '''
+ æ»äº¡åŽäº§ç”Ÿçˆ†ç‚¸!!!
+ ä½ æ‰€çƒçˆ±çš„ï¼Œå°±æ˜¯ä½ çš„ç”Ÿæ´»
+ '''
}
ChickenNuggetBuff: {
- DisplayName: Chicken Nugget Buff
- Description: ""
+ DisplayName: 鸡å—
+ Description:
+ '''
+ å¢žåŠ 1生命回å¤ã€4%攻速!!!
+ 数一数二的鸡å—ï¼
+ '''
}
ChocolateChipCookieBuff: {
- DisplayName: Chocolate Chip Cookie Buff
- Description: ""
+ DisplayName: 巧克力曲奇饼干
+ Description:
+ '''
+ å¢žåŠ 2点生命回å¤å’Œé”力回å¤
+ 补充能é‡
+ '''
}
ChristmasPuddingBuff: {
- DisplayName: Christmas Pudding Buff
- Description: ""
+ DisplayName: 圣诞布ä¸
+ Description:
+ '''
+ 所有å¯å弹射弹多å弹一次ï¼
+ Duang~Duang~Duang~
+ '''
}
CoconutBuff: {
- DisplayName: Coconut Buff
- Description: ""
+ DisplayName: 椰å
+ Description:
+ '''
+ å¢žåŠ 4防御,3%å‡ä¼¤!!!
+ 我从å°å•ƒåˆ°å¤§
+ '''
}
CookedFishBuff: {
- DisplayName: Cooked Fish Buff
- Description: ""
+ DisplayName: 熟鱼
+ Description:
+ '''
+ å¢žåŠ 40é”力上é™,4%锿³•暴击率!!!
+ 益气å¥è„¾
+ '''
}
CookedMarshmallowBuff: {
- DisplayName: Cooked Marshmallow Buff
- Description: ""
+ DisplayName: 熟棉花糖
+ Description:
+ '''
+ å‡å°‘75%最大掉è½é€Ÿåº¦,ä½†æ— æ³•æ“æŽ§ä¸‹è½é€Ÿåº¦!!!
+ 轻飘飘的
+ '''
}
CookedShrimpBuff: {
- DisplayName: Cooked Shrimp Buff
- Description: ""
+ DisplayName: 熟虾
+ Description:
+ '''
+ å¢žåŠ 10防御,4点盔甲穿é€!!!
+ 补钙
+ '''
}
DragonfruitBuff: {
- DisplayName: Dragonfruit Buff
- Description: ""
+ DisplayName: ç«é¾™æžœ
+ Description:
+ '''
+ æ”»å‡»é€ æˆç€ç«ä»¥åŠæ¶‚æ²¹
+ 红红ç«ç«æææƒšæƒš
+ '''
}
ElderberryBuff: {
- DisplayName: Elderberry Buff
- Description: ""
+ DisplayName: 接骨木果
+ Description:
+ '''
+ ä½ å¯ä»¥çŸè·ç¦»å†²åˆº
+ 抗氧化
+ '''
}
EscargotBuff: {
- DisplayName: Escargot Buff
- Description: ""
+ DisplayName: 食用蜗牛
+ Description:
+ '''
+ å¤§å¤§å‰Šå¼±ç§»åŠ¨åŠ›ï¼Œå¢žåŠ 50%å‡ä¼¤!!!
+ ç¥žé¾Ÿè¯æ°´?
+ '''
}
FriedEggBuff: {
- DisplayName: Fried Egg Buff
- Description: ""
+ DisplayName: 煎蛋
+ Description:
+ '''
+ å¢žåŠ 6%伤害!!!
+ 蛋白质
+ '''
}
FriesBuff: {
- DisplayName: Fries Buff
- Description: ""
+ DisplayName: 炸薯æ¡
+ Description:
+ '''
+ åŠ 4防御,6%暴击!!!
+ 高油高ç›
+ '''
}
FroggleBunwichBuff: {
- DisplayName: Froggle Bunwich Buff
- Description: ""
+ DisplayName: 蛙腿三明治
+ Description:
+ '''
+ è‡ªåŠ¨è·³è·ƒï¼Œå¢žåŠ ä¼¤å®³ï¼Œæå‡è·³è·ƒèƒ½åŠ›!!!
+ ä½ èƒ½çœŸæ£å°åˆ°æ²¼æ³½çš„味é“
+ '''
}
FruitSaladBuff: {
- DisplayName: Fruit Salad Buff
- Description: ""
+ DisplayName: 水果沙拉
+ Description:
+ '''
+ æå‡å¤§éƒ¨åˆ†å±žæ€§
+ é•¿ä¹…çš„ç»´ç”Ÿç´ ï¼
+ '''
}
GingerbreadCookieBuff: {
- DisplayName: Gingerbread Cookie Buff
- Description: ""
+ DisplayName: 姜饼
+ Description:
+ '''
+ å¢žåŠ 2生命回å¤,ä¿æš–!!!
+ 驱寒排毒
+ '''
}
GoldenDelightBuff: {
- DisplayName: Golden Delight Buff
- Description: ""
+ DisplayName: 金美味
+ Description:
+ '''
+ æ”»å‡»é€ è¿ˆè¾¾æ–¯ï¼Œæå‡å¤§éƒ¨åˆ†å±žæ€§!!!
+ 金ç¿ç¿!
+ '''
}
GrapefruitBuff: {
- DisplayName: Grapefruit Buff
- Description: ""
+ DisplayName: è‘¡è„æŸš
+ Description:
+ '''
+ åŠ 25%å¬å”¤ç‰©å‡»é€€!!!
+ æ‹’ç»è‚¾é€æ”¯
+ '''
}
GrapesBuff: {
- DisplayName: Grapes Buff
- Description: ""
+ DisplayName: è‘¡è„
+ Description:
+ '''
+ å¢žåŠ 1å¬å”¤æ ,幸è¿å€¼åŠ 10%,å‡12防御!!!
+ 多å多ç¦
+ '''
}
GrilledSquirrelBuff: {
- DisplayName: Grilled Squirrel Buff
- Description: ""
+ DisplayName: 烤æ¾é¼
+ Description:
+ '''
+ æå‡è·³è·ƒèƒ½åŠ›
+ 欢跃
+ '''
}
GrubSoupBuff: {
- DisplayName: Grub Soup Buff
- Description: ""
+ DisplayName: 蛆虫汤
+ Description:
+ '''
+ å¢žåŠ 30渔力,æ¯ç§’å‡2点生命!!!
+ åƒå•¥è¡¥å•¥ï¼Œå°±æ˜¯æœ‰ç‚¹æ¶å¿ƒ
+ '''
}
HotdogBuff: {
- DisplayName: Hotdog Buff
- Description: ""
+ DisplayName: çƒç‹—
+ Description:
+ '''
+ 增强çŸå‰‘与长矛类æ¦å™¨!!!
+ å”~~
+ '''
}
IceCreamBuff: {
- DisplayName: Ice Cream Buff
- Description: ""
+ DisplayName: 冰淇淋
+ Description:
+ '''
+ å…ç–«ç€ç«å’Œç«å—!!!
+ åƒé›ªï¼ˆbushi
+ '''
}
LemonBuff: {
- DisplayName: Lemon Buff
- Description: ""
+ DisplayName: æŸ æª¬
+ Description:
+ '''
+ å¢žåŠ 4%远程暴击,仇æ¨å€¼å‡300
+ 消炎美容
+ '''
}
LobsterTailBuff: {
- DisplayName: Lobster Tail Buff
- Description: ""
+ DisplayName: 龙虾尾
+ Description:
+ '''
+ å¢žåŠ 6防御,33%挖矿速度
+ 壮阳
+ '''
}
MangoBuff: {
- DisplayName: Mango Buff
- Description: ""
+ DisplayName: 芒果
+ Description:
+ '''
+ å‡ç¼“å› é£Ÿç‰©ä¸æ¯’而产生的æŒç»å‡è¡€æ•ˆæžœ
+ 清胃解毒
+ '''
}
MarshmallowBuff: {
- DisplayName: Marshmallow Buff
- Description: ""
+ DisplayName: 棉花糖
+ Description:
+ '''
+ å¯ä»¥äºŒæ®µè·³
+ åƒäº‘ä¸€æ ·
+ '''
}
MonsterLasagnaBuff: {
- DisplayName: Monster Lasagna Buff
- Description: ""
+ DisplayName: 怪物åƒå±‚é¢
+ Description:
+ '''
+ å¢žåŠ 25%暴击率,但æ¯ç§’å‡3生命!!!
+ 弄熟的æ¶é”还是æ¶é”,在åƒå±‚饼ä¸ä¹Ÿä¸ä¼šæ”¹å˜
+ '''
}
NachosBuff: {
- DisplayName: Nachos Buff
- Description: ""
+ DisplayName: 玉米片
+ Description:
+ '''
+ çˆ†ç‚¸ç±»å°„å¼¹çˆ†ç‚¸èŒƒå›´å¢žåŠ ï¼ï¼
+ 爆米花
+ '''
}
PadThaiBuff: {
- DisplayName: Pad Thai Buff
- Description: ""
+ DisplayName: æ³°å¼ç‚’é¢
+ Description:
+ '''
+ å¢žåŠ 50%å¬å”¤ç‰©å‡»é€€
+ 异域风情
+ '''
}
PeachBuff: {
- DisplayName: Peach Buff
- Description: ""
+ DisplayName: 桃å
+ Description:
+ '''
+ å¢žåŠ å¿ƒçš„æ‹¾å–范围,1生命回å¤
+ 在想peach
+ '''
}
PhoBuff: {
- DisplayName: Pho Buff
- Description: ""
+ DisplayName: è¶Šå—æ²³ç²‰
+ Description:
+ '''
+ å¢žåŠ 8%å¬å”¤ç‰©ä¼¤å®³!!!
+ 异域风情
+ '''
}
PineappleBuff: {
- DisplayName: Pineapple Buff
- Description: ""
+ DisplayName: è è
+ Description:
+ '''
+ 近战攻击者伤害玩家时会承å—一åŠä¼¤å®³!!!
+ è è碱
+ '''
}
PizzaBuff: {
- DisplayName: Pizza Buff
- Description: ""
+ DisplayName: 披è¨
+ Description:
+ '''
+ å¢žåŠ 10点盔甲穿é€!!!
+ 会让æ„å¤§åˆ©äººç ´é˜²çš„è èæŠ«è¨
+ '''
}
PlumBuff: {
- DisplayName: Plum Buff
- Description: ""
+ DisplayName: æŽå
+ Description:
+ '''
+ å¢žåŠ 600仇æ¨å€¼ï¼Œ8%攻速!!!
+ 至于我的建议,还是å†ç‰ç‰å§!
+ '''
}
PotatoChipsBuff: {
- DisplayName: Potato Chips Buff
- Description: ""
+ DisplayName: 薯片
+ Description:
+ '''
+ å¢žåŠ 4防御,8%伤害!!!
+ 高油高ç›
+ '''
}
PumpkinPieBuff: {
- DisplayName: Pumpkin Pie Buff
- Description: ""
+ DisplayName: å—瓜派
+ Description:
+ '''
+ å¢žåŠ 50最大生命值!!!
+ 丰收的喜悦
+ '''
}
RambutanBuff: {
- DisplayName: Rambutan Buff
- Description: ""
+ DisplayName: 红毛丹
+ Description:
+ '''
+ å…疫许多å‡ç›Š!!!
+ æé«˜å…ç–«
+ '''
}
RoastedBirdBuff: {
- DisplayName: Roasted Bird Buff
- Description: ""
+ DisplayName: 烤鸟
+ Description:
+ '''
+ æå‡é£žè¡Œèƒ½åŠ›!!!
+ 我是一åªå°å°å°é¸Ÿ
+ '''
}
RoastedDuckBuff: {
- DisplayName: Roasted Duck Buff
- Description: ""
+ DisplayName: 烤é¸
+ Description:
+ '''
+ å¯ä»¥åœ¨æ°´ä¸Šè¡Œèµ°ï¼Œæå‡é£žè¡Œèƒ½åŠ›!!!
+ 这是烤é¸
+ '''
}
SashimiBuff: {
- DisplayName: Sashimi Buff
- Description: ""
+ DisplayName: 生鱼片
+ Description:
+ '''
+ å¯ä»¥æ¸¸æ³³ï¼Œæ°´ä¸‹å‘¼å¸ï¼Œå¢žåŠ 15%伤害,但æ¯ç§’å‡å°‘2点生命!!!
+ 寄生虫ï¼
+ '''
}
SauteedFrogLegsBuff: {
- DisplayName: Sauteed Frog Legs Buff
- Description: ""
+ DisplayName: 炒蛙腿
+ Description:
+ '''
+ 自动跳跃,æå‡è·³è·ƒèƒ½åŠ›!!!
+ é’“ä¸åˆ°è›™è…¿ï¼Ÿé‚£å°±åƒå§ã€‚
+ '''
}
SeafoodDinnerBuff: {
- DisplayName: Seafood Dinner Buff
- Description: ""
+ DisplayName: 海鲜大é¤
+ Description:
+ '''
+ å¢žåŠ 8%暴击,伤害,攻速,爆伤!!!
+ 够生猛ï¼
+ '''
}
ShrimpPoBoyBuff: {
- DisplayName: Shrimp Po Boy Buff
- Description: ""
+ DisplayName: 鲜虾三明治
+ Description:
+ '''
+ å¢žåŠ 6防御,25%挖矿速度
+ 壮阳
+ '''
}
ShuckedOysterBuff: {
- DisplayName: Shucked Oyster Buff
- Description: ""
+ DisplayName: 去壳牡蛎
+ Description:
+ '''
+ å‡å°‘5é˜²å¾¡ï¼ŒåŠ 10点盔甲穿é€ï¼Œæ¯ç§’å‡å°‘3点生命!!!
+ 寄生虫ï¼
+ '''
}
SpaghettiBuff: {
- DisplayName: Spaghetti Buff
- Description: ""
+ DisplayName: æ„大利é¢
+ Description:
+ '''
+ å¢žåŠ 1哨兵æ !!!
+ 异域风情
+ '''
}
StarfruitBuff: {
- DisplayName: Starfruit Buff
- Description: ""
+ DisplayName: æ¨æ¡ƒ
+ Description:
+ '''
+ 使用霰弹枪类æ¦å™¨æ—¶ä¼šå¤šå°„出一å‘åå¼¹
+ 1437大å¸çš„æ·«å¨
+ '''
}
SteakBuff: {
- DisplayName: Steak Buff
- Description: ""
+ DisplayName: 牛排
+ Description:
+ '''
+ å‡å°‘20%é”力消耗!!!
+ 上æµ
+ '''
}
SugarCookieBuff: {
- DisplayName: Sugar Cookie Buff
- Description: ""
+ DisplayName: 蜜糖饼干
+ Description:
+ '''
+ å¢žåŠ 5%远程伤害!!!
+ 养胃滋润
+ '''
}
AleBuff: {
- DisplayName: Ale Buff
- Description: ""
+ DisplayName: 麦芽酒
+ Description:
+ '''
+ çŸæ—¶é—´å†…éžå的范围和速度æå‡è‡³1.5å€!!!
+ è€é…’ç–¯
+ '''
}
AppleJuiceBuff: {
- DisplayName: Apple Juice Buff
- Description: ""
+ DisplayName: 苹果æ±
+ Description:
+ '''
+ çŸæ—¶é—´å†…å¢žåŠ 60%å‡ä¼¤!!!
+ 一天一苹果,医生远离我
+ '''
}
BananaDaiquiriBuff: {
- DisplayName: Banana Daiquiri Buff
- Description: ""
+ DisplayName: 冰冻香蕉代基里
+ Description:
+ '''
+ çŸæ—¶é—´å†…䏿¶ˆè€—åå¼¹ï¼Œå¤§å¹…å¢žåŠ è¿œç¨‹ä¼¤å®³ä¸Žæš´å‡»
+ 低体温血压
+ '''
}
BloodyMoscatoBuff: {
- DisplayName: Bloody Moscato Buff
- Description: ""
+ DisplayName: 血腥éºé¦™è‘¡è„
+ Description:
+ '''
+ çŸæ—¶é—´å†…æ¯æ¬¡æ”»å‡»å›ž1点生命!!!
+ 血色
+ '''
}
CoffeeCupBuff: {
- DisplayName: Coffee Cup Buff
- Description: ""
+ DisplayName: å’–å•¡
+ Description:
+ '''
+ çŸæ—¶é—´å†…å¤§å¹…å¢žåŠ é“ºå¢™é“ºç –é€Ÿåº¦ï¼Œé«˜äº®æ ‡è®°æ•Œäººã€é™·é˜±å’Œå®è—,并散å‘光芒!!!
+ 社畜的å®ç‰©
+ '''
}
CreamSodaBuff: {
- DisplayName: Cream Soda Buff
- Description: ""
+ DisplayName: å¥¶æ²¹è‹æ‰“æ°´
+ Description:
+ '''
+ çŸæ—¶é—´å†…å¤§å¹…å¢žåŠ è¿‘æˆ˜èƒ½åŠ›ï¼Œä½†æžå…¶å¸å¼•仇æ¨
+ å–·å°„ï¼
+ '''
}
FruitJuiceBuff: {
- DisplayName: Fruit Juice Buff
- Description: ""
+ DisplayName: æžœæ±
+ Description:
+ '''
+ çŸæ—¶é—´å†…幅大大æå‡å¤§éƒ¨åˆ†å±žæ€§
+ ç»´ç”Ÿç´ ï¼
+ '''
}
GrapeJuiceBuff: {
- DisplayName: Grape Juice Buff
- Description: ""
+ DisplayName: è‘¡è„æ±
+ Description:
+ '''
+ çŸæ—¶é—´ä½ å˜å¾—æžå…¶å¹¸è¿
+ 浓缩的幸ç¦
+ '''
}
LemonadeBuff: {
- DisplayName: Lemonade Buff
- Description: ""
+ DisplayName: æŸ æª¬æ°´
+ Description:
+ '''
+ çŸæ—¶é—´å†…è¿œç¨‹å‡»é€€åŠ å€,仇æ¨å€¼å‡2400
+ 消炎美容
+ '''
}
MilkCartonBuff: {
- DisplayName: Milk Carton Buff
- Description: ""
+ DisplayName: 盒装牛奶
+ Description:
+ '''
+ çŸæ—¶é—´å†…å…ç–«å‡ ä¹Žæ‰€æœ‰debuff
+ 一奶解百毒
+ '''
}
MilkshakeBuff: {
- DisplayName: Milkshake Buff
- Description: ""
+ DisplayName: 奶昔
+ Description:
+ '''
+ çŸæ—¶é—´å†…å¤§å¹…åŠ ç§»é€Ÿ
+ 节食å‡è‚¥
+ '''
}
PeachSangriaBuff: {
- DisplayName: Peach Sangria Buff
- Description: ""
+ DisplayName: æ¡ƒåæžœé…’
+ Description:
+ '''
+ çŸæ—¶é—´å†…大幅回å¤ç”Ÿå‘½ï¼Œå¢žåŠ å¿ƒçš„æ‹¾å–范围
+ 我也是桃饱用户
+ '''
}
PinaColadaBuff: {
- DisplayName: Pina Colada Buff
- Description: ""
+ DisplayName: 椰林飘香
+ Description:
+ '''
+ çŸæ—¶é—´å†…近战攻击者伤害玩家时会承å—10å€ï¼ˆä¸Šé™1000)伤害!!!
+ ä»Žä¸æ·»åŠ é¦™ç²¾å½“ç”Ÿæ¦¨
+ '''
}
PrismaticPunchBuff: {
- DisplayName: Prismatic Punch Buff
- Description: ""
+ DisplayName: 七彩潘趣酒
+ Description:
+ '''
+ çŸæ—¶é—´å†…å¢žåŠ 5å¬å”¤æ ,5哨兵æ ï¼Œå¢žåŠ 50%å¬å”¤ä¼¤å®³ï¼Œå‡»é€€!!!
+ 高雅兴致
+ '''
}
SakeBuff: {
- DisplayName: Sake Buff
- Description: ""
+ DisplayName: 清酒
+ Description:
+ '''
+ çŸæ—¶é—´å†…å‡å°‘18é˜²å¾¡ï¼Œå¤§å¹…å¢žåŠ è¿‘æˆ˜èƒ½åŠ›!!!
+ 纯度,太高了
+ '''
}
SmoothieofDarknessBuff: {
- DisplayName: Smoothieof Darkness Buff
- Description: ""
+ DisplayName: 暗黑奶昔
+ Description:
+ '''
+ çŸæ—¶é—´å†…有60%çš„æ¦‚çŽ‡é—ªé¿æ”»å‡»!!!
+ 腹黑(å—颿„义上)
+ '''
}
TeacupBuff: {
- DisplayName: Teacup Buff
- Description: ""
+ DisplayName: 一æ¯èŒ¶
+ Description:
+ '''
+ çŸæ—¶é—´å†…å¤§å¹…å¢žåŠ é”力回å¤ï¼Œé”法伤害,暴击!!!
+ 醇香四溢
+ '''
}
TropicalSmoothieBuff: {
- DisplayName: Tropical Smoothie Buff
- Description: ""
+ DisplayName: çƒå¸¦å¥¶æ˜”
+ Description:
+ '''
+ çŸæ—¶é—´å†…锿³•攻击仅消耗一点é”åŠ›ï¼Œå¤§å¹…å¢žåŠ é”æ³•伤害,暴击!!!
+ çƒå¸¦é£Žæš´
+ '''
}
ArcticshellfishWarshipBuff: {
- DisplayName: Arcticshellfish Warship Buff
- Description: ""
+ DisplayName: 北æžè´å†›èˆ°
+ Description:
+ '''
+ æå‡4防御
+ 美味的北æžè´å†›èˆ°
+ '''
}
BakedMusselBuff: {
- DisplayName: Baked Mussel Buff
- Description: ""
+ DisplayName: ç‚烧é’å£è´
+ Description:
+ '''
+ å¢žåŠ 6%爆伤ã€4防御
+ 似乎没那么生猛了
+ '''
}
BakedOysterBuff: {
- DisplayName: Baked Oyster Buff
- Description: ""
+ DisplayName: ç‚烧生èš
+ Description:
+ '''
+ å¢žåŠ 4点盔甲穿é€ã€4防御
+ è€é…’ç–¯
+ '''
}
CantaloupeJellyBuff: {
- DisplayName: Cantaloupe Jelly Buff
- Description: ""
+ DisplayName: 哈密瓜果冻
+ Description:
+ '''
+ å°„å¼¹å¯ä»¥å¤šç©¿é€ä¸€æ¬¡
+ duang~duang~duang~
+ '''
}
CaramelPuddingBuff: {
- DisplayName: Caramel Pudding Buff
- Description: ""
+ DisplayName: 焦糖布ä¸
+ Description:
+ '''
+ å°„å¼¹å¯ä»¥å¤šå弹一次
+ duang~duang~duang~
+ '''
}
CrabseedWarshipBuff: {
- DisplayName: Crabseed Warship Buff
- Description: ""
+ DisplayName: 蟹籽军舰
+ Description:
+ '''
+ æå‡æš´å‡»çއ
+ 美味的蟹籽军舰
+ '''
}
DurianBuff: {
- DisplayName: Durian Buff
- Description: ""
+ DisplayName: 榴莲
+ Description:
+ '''
+ åŠ å¿«æ¶ˆåŒ–é£Ÿç‰©çš„é€Ÿåº¦
+ 促进消化
+ '''
}
EggTartBuff: {
- DisplayName: Egg Tart Buff
- Description: ""
+ DisplayName: 蛋挞
+ Description:
+ '''
+ å¢žåŠ 5%暴击伤害
+ 这酥皮ä¸é”™
+ '''
}
KiwiFruitBuff: {
- DisplayName: Kiwi Fruit Buff
- Description: ""
+ DisplayName: 猕猴桃
+ Description:
+ '''
+ 增大20%æ¦å™¨å¤§å°
+ åˆç§°å¥‡å¼‚æžœ
+ '''
}
KiwiIceCreamBuff: {
- DisplayName: Kiwi Ice Cream Buff
- Description: ""
+ DisplayName: 猕猴桃冰激凌
+ Description:
+ '''
+ 增大10%æ¦å™¨å¤§å°ï¼ŒåŠ å¿«æ¦å™¨æ”»é€Ÿ
+ 奇异的力é‡
+ '''
}
MangosteenBuff: {
- DisplayName: Mangosteen Buff
- Description: ""
+ DisplayName: 山竹
+ Description:
+ '''
+ æå‡å›žæ—‹é•–ï¼Œæ‚ æ‚ çƒã€é“¾æž·ç±»æ¦å™¨è·ç¦»
+ 补养之效
+ '''
}
MapoTofuBuff: {
- DisplayName: Mapo Tofu Buff
- Description: ""
+ DisplayName: 麻婆豆è…
+ Description:
+ '''
+ TODO
+ '''
}
OrangeIcecreamBuff: {
- DisplayName: Orange Icecream Buff
- Description: ""
+ DisplayName: 香橙冰激凌
+ Description:
+ '''
+ å»¶é•¿æ— æ•Œå¸§æ—¶é—´
+ 真实å˜äºŽå¿ƒä¸
+ '''
}
SalmonInPepperBuff: {
- DisplayName: Salmon In Pepper Buff
- Description: ""
+ DisplayName: 椒ç›ä¸‰æ–‡é±¼
+ Description:
+ '''
+ æå‡é€Ÿåº¦,尤其是在水ä¸
+ 冰海之皇
+ '''
}
SalmonWarshipBuff: {
- DisplayName: Salmon Warship Buff
- Description: ""
+ DisplayName: 三文鱼军舰
+ Description:
+ '''
+ æå‡é€Ÿåº¦
+ 美味的三文鱼军舰
+ '''
}
SeafoodPizzaBuff: {
- DisplayName: Seafood Pizza Buff
- Description: ""
+ DisplayName: 海鲜披è¨
+ Description:
+ '''
+ æå‡å¤§éƒ¨åˆ†å±žæ€§
+ 一个人åƒå®Œè¿™ä¸ªå¯ä¸å®¹æ˜“
+ '''
}
StinkyTofuBuff: {
- DisplayName: Stinky Tofu Buff
- Description: ""
+ DisplayName: è‡è±†è…
+ Description:
+ '''
+ 使é 近的敌怪混乱
+ åˆé¦™åˆè‡
+ '''
}
StrawberryBuff: {
DisplayName: Strawberry Buff
- Description: ""
+ Description:
+ '''
+ æ•Œæ€ªè¶Šè¿‘ï¼Œé€ æˆçš„伤害越高
+ å—人欢迎的水果
+ '''
}
StrawberryIcecreamBuff: {
- DisplayName: Strawberry Icecream Buff
- Description: ""
+ DisplayName: è‰èŽ“å†°æ¿€å‡Œ
+ Description:
+ '''
+ æ•Œæ€ªè¶Šè¿‘ï¼Œé€ æˆçš„伤害越高
+ å†°å†·å¦‚ä½ ï¼Œä¾æ—§ä»¤äººçˆ±ä¸å¿é‡Š
+ '''
}
SweetshrimpSushiBuff: {
- DisplayName: Sweetshrimp Sushi Buff
- Description: ""
+ DisplayName: 甜虾寿å¸
+ Description:
+ '''
+ æå‡æ”»å‡»
+ 美味的甜虾寿å¸
+ '''
}
TamakoSushiBuff: {
- DisplayName: Tamako Sushi Buff
- Description: ""
+ DisplayName: 玉å寿å¸
+ Description:
+ '''
+ æå‡ç”Ÿå‘½å›žå¤
+ 美味的玉å寿å¸
+ '''
}
WakameWarshipBuff: {
- DisplayName: Wakame Warship Buff
- Description: ""
+ DisplayName: 裙带èœå¯¿å¸
+ Description:
+ '''
+ æå‡é”力回å¤
+ 美味的裙带èœå¯¿å¸
+ '''
}
WatermelonBuff: {
- DisplayName: Watermelon Buff
- Description: ""
+ DisplayName: 西瓜
+ Description:
+ '''
+ 增强8%击退能力
+ 最大的打击力度
+ '''
}
WatermelonPlateBuff: {
- DisplayName: Watermelon Plate Buff
- Description: ""
+ DisplayName: 西瓜拼盘
+ Description:
+ '''
+ æå‡6%暴击率和暴击伤害
+ æœ´å®žæ— åŽçš„æ‘†ç›˜
+ '''
}
BlueHawaiiBuff: {
- DisplayName: Blue Hawaii Buff
- Description: ""
+ DisplayName: è“色å¤å¨å¤·
+ Description:
+ '''
+ çŸæ—¶é—´å†…射弹速度获得æå‡
+ æµ·é£Žå¹æ‹‚
+ '''
}
B_52Buff: {
- DisplayName: B_52 Buff
- Description: ""
+ DisplayName: B_52
+ Description:
+ '''
+ çŸæ—¶é—´å†…大幅æå‡å‘å°„å™¨é€Ÿåº¦ã€æš´å‡»ã€ä¼¤å®³
+ 轰炸机
+ '''
}
DreamYearningBuff: {
- DisplayName: Dream Yearning Buff
- Description: ""
+ DisplayName: 梦里人
+ Description:
+ '''
+ çŸæ—¶é—´å†…射弹速度获得æå‡
+ æ€å›å¿†å›ï¼Œé‚牵梦è¦ï¼Œç¿ 销香暖云å±ï¼Œæ›´å“ªå ªé…’醒
+ '''
}
DryMartiniBuff: {
- DisplayName: Dry Martini Buff
- Description: ""
+ DisplayName: 干马天尼
+ Description:
+ '''
+ çŸæ—¶é—´å¤§å¹…æå‡æ”»å‡»
+ ç»å…¸ä¹‹ä½œ
+ '''
}
GreenStormBuff: {
- DisplayName: Green Storm Buff
- Description: ""
+ DisplayName: 绿å¶é£Žæš´
+ Description:
+ '''
+ çŸæ—¶é—´äº¤æ›¿å°„出å¶ç»¿æ°´æ™¶å’Œå¢å云
+ 别以为è‰ä¾¿å®œ,没上规模å‰,å®ƒæ¯”è‹¹æžœæ ¸æ¡ƒä»€ä¹ˆçš„éƒ½è´µ
+ '''
}
KiwiJuiceBuff: {
- DisplayName: Kiwi Juice Buff
- Description: ""
+ DisplayName: 猕猴桃æ±
+ Description:
+ '''
+ çŸæ—¶é—´å†…大幅增大æ¦å™¨å¤§å°
+ 浓缩的奇异之力
+ '''
}
LonelyJellyfishBuff: {
- DisplayName: Lonely Jellyfish Buff
- Description: ""
+ DisplayName: å¤ç‹¬çš„æ°´æ¯
+ Description:
+ '''
+ çŸæ—¶é—´å†…䏿–äºŽé¼ æ ‡å¤„ç”Ÿæˆæ°´æ¯ç”µåœˆï¼Œå¹¶ä¸”获得éšèº«èƒ½åŠ›
+ è§‚èµå®Œå°±ä¸€é¥®è€Œå°½å§
+ '''
}
OrangeJuiceBuff: {
- DisplayName: Orange Juice Buff
- Description: ""
+ DisplayName: æ©™æ±
+ Description:
+ '''
+ çŸæ—¶é—´å†…èŽ·å¾—è¶…é•¿æ— æ•Œå¸§
+ 嗯,有点åƒLCL
+ '''
}
PiercoldWindBuff: {
- DisplayName: Piercold Wind Buff
- Description: ""
+ DisplayName: ç²¾çµè²ä»•
+ Description:
+ '''
+ 对ç¯ç¬¼æœˆæ•Œæ€ªç‰¹æ”»
+ 长啸出原野,凛然寒风生
+ '''
}
PurpleHooterBuff: {
- DisplayName: Purple Hooter Buff
- Description: ""
+ DisplayName: æ¢¦å¹»èŽ«å‰æ‰˜
+ Description:
+ '''
+ 对血月敌怪特攻
+ 高贵与深沉
+ '''
}
QuinceMarryBuff: {
- DisplayName: Quince Marry Buff
- Description: ""
+ DisplayName: 血腥玛丽
+ Description:
+ '''
+ 对å—瓜月敌怪特攻
+ ç‚™çƒä¸Žæ¸©æŸ”
+ '''
}
RedWineBuff: {
- DisplayName: Red Wine Buff
- Description: ""
+ DisplayName: 红酒
+ Description:
+ '''
+ 对霜月敌怪特攻
+ 上æµä¸Žä¼˜é›…
+ '''
}
SunriseBuff: {
- DisplayName: Sunrise Buff
- Description: ""
+ DisplayName: 龙舌兰日出
+ Description:
+ '''
+ 对日食敌怪特攻
+ 阳光与明媚
+ '''
}
TricolourBuff: {
- DisplayName: Tricolour Buff
- Description: ""
+ DisplayName: 环游世界
+ Description:
+ '''
+ å¯¹è€æ€ªä»†ä»Žç‰¹æ”»
+ 夿‚与专一
+ '''
}
WaterMelonJuiceBuff: {
- DisplayName: Water Melon Juice Buff
- Description: ""
+ DisplayName: 西瓜æ±
+ Description:
+ '''
+ çŸæ—¶é—´å¤§å¹…å¢žåŠ å‡»é€€ä¸Žæš´å‡»
+ 浓缩的打击力度
+ '''
}
ShortImmune12: {
- DisplayName: Short Immune12
+ DisplayName: æ›´çŸçš„æ— 敌帧
Description: ""
}
ShortImmune3: {
- DisplayName: Short Immune3
+ DisplayName: æ›´çŸçš„æ— 敌帧
Description: ""
}
ElementalResistanceReductionDebuffTest: {
- DisplayName: Elemental Resistance Reduction Debuff Test
+ DisplayName: å…ƒç´ æŠ—æ€§é™ä½Ž
Description: ""
}
Petrification: {
- DisplayName: Petrification
+ DisplayName: 石化
Description: ""
}
TuskCursed: {
- DisplayName: Tusk Cursed
+ DisplayName: ç 牙的诅咒
Description: ""
}
TuskStaff: {
- DisplayName: Tusk Staff
- Description: ""
+ DisplayName: ç 牙法æ–
+ Description: "飞ç ç‰™ä¸ºä½ è€Œæˆ˜"
}
FireflyInferno: {
- DisplayName: Firefly Inferno
+ DisplayName: è¤ç«çƒˆç„°
Description: ""
}
GlowMothBuff: {
- DisplayName: Glow Moth Buff
+ DisplayName: 夜光飞蛾
Description: ""
}
OnMoth: {
- DisplayName: On Moth
+ DisplayName: 被幻è¶è¤ç«æ‰‡æ ‡è®°
Description: ""
}
ShadowPotionBuff: {
- DisplayName: Shadow Potion Buff
- Description: ""
+ DisplayName: æš—å½±è¯æ°´
+ Description: "在暗处æå‡åŸºç¡€å±žæ€§"
}
Freeze: {
- DisplayName: Freeze
+ DisplayName: 冰冻
Description: ""
}
LaserWormBuff: {
- DisplayName: Laser Worm Buff
+ DisplayName: 激光虫
Description: ""
}
ShadowSupervisor: {
- DisplayName: Shadow Supervisor
+ DisplayName: 暗夜观察者
Description: ""
}
MoonAndFragrans: {
- DisplayName: Moon And Fragrans
+ DisplayName: 月夜æµèг
Description: ""
}
MoonAndFragransII: {
- DisplayName: Moon And FragransII
+ DisplayName: 月夜æµèг2
Description: ""
}
MoonAndFragransIII: {
- DisplayName: Moon And FragransIII
+ DisplayName: 月夜æµèг3
Description: ""
}
BlueImmune: {
- DisplayName: Blue Immune
+ DisplayName: å…ç–«è“ç«
Description: ""
}
BrownImmune: {
- DisplayName: Brown Immune
+ DisplayName: å…疫棕ç«
Description: ""
}
GreenImmune: {
- DisplayName: Green Immune
+ DisplayName: å…疫绿ç«
Description: ""
}
PinkImmune: {
- DisplayName: Pink Immune
+ DisplayName: å…疫粉ç«
Description: ""
}
PurpleImmune: {
- DisplayName: Purple Immune
+ DisplayName: å…ç–«ç´«ç«
Description: ""
}
RedImmune: {
- DisplayName: Red Immune
+ DisplayName: å…疫红ç«
Description: ""
}
WhiteImmune: {
- DisplayName: White Immune
+ DisplayName: å…疫白ç«
Description: ""
}
YellowImmune: {
- DisplayName: Yellow Immune
+ DisplayName: å…疫黄ç«
Description: ""
}
AcytaeaInferno: {
- DisplayName: Acytaea Inferno
+ DisplayName: 雅斯塔亚的烈ç«
Description: ""
}
CactusBallBuff: {
- DisplayName: Cactus Ball Buff
+ DisplayName: 仙人掌çƒ
Description: ""
}
WaterBoltII: {
- DisplayName: Water BoltII
+ DisplayName: æ°´ç®II
Description: ""
}
AmberStick: {
- DisplayName: Amber Stick
+ DisplayName: 黿€§ç¥ç€
Description: ""
}
Armor15Cracked: {
- DisplayName: Armor15 Cracked
- Description: ""
+ DisplayName: 盔甲碎裂
+ Description: "防御力é™ä½Ž15"
}
AuburnBell: {
- DisplayName: Auburn Bell
- Description: ""
+ DisplayName: 金棕铃铛
+ Description: "金棕飞æ£ä¸ºä½ 而战"
}
AuburnSelfReinforcing: {
- DisplayName: Auburn Self Reinforcing
- Description: ""
+ DisplayName: 金棕之力
+ Description: "生命缓慢枯èŽä»¥æ¢å–+1å¬å”¤æ ä½"
}
BloodCultistBuff: {
- DisplayName: Blood Cultist Buff
- Description: ""
+ DisplayName: 血月教徒的ç¥ç¦
+ Description: "生命缓慢回å¤"
}
Charred: {
- DisplayName: Charred
- Description: ""
+ DisplayName: 焚烧
+ Description: "大幅é™ä½Žé˜²å¾¡å¹¶ä¸”生命高速æµå¤±"
}
CrossHair: {
- DisplayName: Cross Hair
+ DisplayName: 头å‘交å‰
Description: ""
}
CyanVineRingCrit: {
- DisplayName: Cyan Vine Ring Crit
- Description: ""
+ DisplayName: é’缎指环的ç¥ç¦
+ Description: "暴击+4%"
}
DeadBeetleEggBuff: {
- DisplayName: Dead Beetle Egg Buff
- Description: ""
+ DisplayName: æ»ç”²è™«åµ
+ Description: "å¤ç”Ÿçš„ç”²è™«éª¨éª¼ä¸ºä½ è€Œæˆ˜"
}
EvilMusicRemnant: {
- DisplayName: Evil Music Remnant
- Description: ""
+ DisplayName: é”律残ç«
+ Description: "ä½ å¥å“了远å¤é—è½çš„ä¹è°±"
}
GuideBuff: {
- DisplayName: Guide Buff
- Description: ""
+ DisplayName: 引领
+ Description: "å‘出光芒"
}
HasHitByResistenceWireBayonet: {
- DisplayName: Has Hit By Resistence Wire Bayonet
+ DisplayName: 被电阻刺剑命ä¸
Description: ""
}
HexaCrystalWeak: {
- DisplayName: Hexa Crystal Weak
- Description: ""
+ DisplayName: 暮晶脆弱
+ Description: "éå—æ‰€æœ‰é™„带暮光晶体的攻击时å—到更多伤害"
}
IstafelsSunfireGraspFireBallBuff: {
- DisplayName: Istafels Sunfire Grasp Fire Ball Buff
- Description: ""
+ DisplayName: 伊斯塔裴尔的阳炎ç«çƒ
+ Description: "é€ æˆæ³•术伤害å¯ä»¥ç»™å®ƒå……能"
}
IstafelsSunfireGraspSkillBuff: {
- DisplayName: Istafels Sunfire Grasp Skill Buff
+ DisplayName: 伊斯塔裴尔的阳炎战技
Description: ""
}
JellyBallStick: {
- DisplayName: Jelly Ball Stick
- Description: ""
+ DisplayName: é™·å…¥çƒå†»
+ Description: "速度大幅下é™"
}
MeltingSideGyroscopeBuff: {
- DisplayName: Melting Side Gyroscope Buff
- Description: ""
+ DisplayName: 熔边陀螺
+ Description: "用éžå抽打陀螺å¯ä»¥å……能"
}
Photolysis: {
- DisplayName: Photolysis
- Description: ""
+ DisplayName: 光解
+ Description: "暴露在光线下会燃烧血液"
}
Plague: {
- DisplayName: Plague
+ DisplayName: 瘟疫
Description: ""
}
RayBuff: {
- DisplayName: Ray Buff
+ DisplayName: 射线
Description: ""
}
RustSlingshotBuffOne: {
- DisplayName: Rust Slingshot Buff One
+ DisplayName: 锈弹弓
Description: ""
}
RustSlingshotBuffTwo: {
- DisplayName: Rust Slingshot Buff Two
+ DisplayName: 锈弹弓2
Description: ""
}
RustSlingshotBuffThree: {
- DisplayName: Rust Slingshot Buff Three
+ DisplayName: 锈弹弓3
Description: ""
}
SpritialDamage: {
- DisplayName: Spritial Damage
+ DisplayName: 精神æŸä¼¤
Description: ""
}
YggdrasilStoneGyroscopeBuff: {
- DisplayName: Yggdrasil Stone Gyroscope Buff
- Description: ""
+ DisplayName: 天穹岩陀螺
+ Description: "用éžå抽打陀螺å¯ä»¥å……能"
}
BadrBuff: {
- DisplayName: Badr Buff
- Description: ""
+ DisplayName: å·´å¾·å°”
+ Description: "点亮å‰è¡Œçš„è·¯"
}
LampWoodSeedBuff: {
- DisplayName: Lamp Wood Seed Buff
- Description: ""
+ DisplayName: ç¯æœ¨ç§å
+ Description: "未å‘芽的光"
}
JellyBubbleMount: {
- DisplayName: Jelly Bubble Mount
- Description: ""
+ DisplayName: çƒå†»æ³¡æ³¡å骑
+ Description: "ä¸ç¨³å®šæµ®ç©º"
}
CorrosiveDebuff: {
- DisplayName: Corrosive Debuff
- Description: ""
+ DisplayName: 侵蚀
+ Description: "移速和防御下é™"
}
DevilHeartGyroscopeBuff: {
- DisplayName: Devil Heart Gyroscope Buff
- Description: ""
+ DisplayName: é”心陀螺
+ Description: "用éžå抽打陀螺å¯ä»¥å……能"
}
DevilHeartWeaponBuff: {
- DisplayName: Devil Heart Weapon Buff
+ DisplayName: é”心æ¦å™¨ç¥ç¦
Description: ""
}
FractureDebuff: {
- DisplayName: Fracture Debuff
- Description: ""
+ DisplayName: ç ´ç»½
+ Description: "å—伤时é¢å¤–å—到50%的伤害"
}
HardenedSkinBuff: {
- DisplayName: Hardened Skin Buff
- Description: ""
+ DisplayName: 硬化皮肤
+ Description: "å—到伤害下é™90%"
}
LegumeGyroscopeBuff: {
- DisplayName: Legume Gyroscope Buff
- Description: ""
+ DisplayName: 裂èšé™€èžº
+ Description: "用éžå抽打陀螺å¯ä»¥å……能"
}
LichenInfected: {
- DisplayName: Lichen Infected
- Description: ""
+ DisplayName: çœŸèŒæ„ŸæŸ“
+ Description: "è¿™äº›ä¸œè¥¿ä¼šé€šè¿‡æ´»ç‰©ç¹æ®–"
}
LivingWoodplateBuff: {
- DisplayName: Living Woodplate Buff
- Description: ""
+ DisplayName: 活木甲
+ Description: "å¢žåŠ é˜²å¾¡ï¼Œå¼„æ¹¿åŽè¿›ä¸€æ¥å¼ºåŒ–效果且æ¢å¤ç”Ÿå‘½"
}
MolluscsSetBuff: {
- DisplayName: Molluscs Set Buff
- Description: ""
+ DisplayName: 软体的特性
+ Description:
+ '''
+ 获得水下呼å¸ï¼Œæ°´ä¸‹åŠ é€Ÿæ•ˆæžœ
+ æ ¹æ®å¤´ç›”ä¸åŒï¼ŒèŽ·å¾—ä»¥ä¸‹æ•ˆæžœ
+ çç 软体: +2生命å†ç”Ÿï¼Œ+10%近战攻速
+ 附苔软体: +15%æ¦‚çŽ‡ä¸æ¶ˆè€—å¼¹è¯ï¼Œ+3盔甲穿é€
+ '''
}
MossCover: {
- DisplayName: Moss Cover
- Description: ""
+ DisplayName: 苔藓皮层
+ Description: "防御+5å¹¶å…疫侵蚀"
}
RuinSetBuff: {
- DisplayName: Ruin Set Buff
- Description: ""
+ DisplayName: é—迹ç¥ç¦
+ Description: "+25%移速和10%å¬å”¤ä¼¤å®³"
}
TheGreenSolarBuff: {
- DisplayName: The Green Solar Buff
- Description: ""
+ DisplayName: 绿阳之石
+ Description: "ä½ å¤„äºŽæ¶…æ§ƒçŠ¶æ€ï¼Œä¸ä¼šæ»äº¡ä¸”ç¼ä¼¤é™„近敌人"
}
WitherbarkSetBuff: {
- DisplayName: Witherbark Set Buff
- Description: ""
+ DisplayName: 枯木的ç¥ç¦
+ Description: "+3å¬å”¤æ 但是å¬å”¤ä¼¤å®³-30%,枯木护å«ä¸ºä½ 而战"
}
WoodlandWraithStaffBuff: {
- DisplayName: Woodland Wraith Staff Buff
- Description: ""
+ DisplayName: 森宇幽é‚的齿èŒ
+ Description: "飞行的血齿èŒä¸ºä½ 而战"
}
WoodlandWraithStaffMyceliumBuff: {
- DisplayName: Woodland Wraith Staff Mycelium Buff
- Description: ""
+ DisplayName: 森宇幽é‚çš„èŒä¸
+ Description: "缓慢回å¤ç”Ÿå‘½ï¼Œåœ¨å¢åäº‘åŒºåŸŸä¸æ•ˆæžœå¢žå¼º"
}
DeathFlame: {
- DisplayName: Death Flame
- Description: ""
+ DisplayName: æ»ç¥žçƒˆç«
+ Description: "越接近æ»äº¡è¶Šææƒ§æ»äº¡"
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Accessories.Wings.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Accessories.Wings.hjson
index e34ed64ac..e27142fcd 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Accessories.Wings.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Accessories.Wings.hjson
@@ -1,4 +1,4 @@
BlueyWings: {
- DisplayName: Bluey Wings
+ DisplayName: è“æ²³ä¹‹ç¿¼
Tooltip: ""
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Accessories.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Accessories.hjson
index 1287f8159..aeddeb15a 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Accessories.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Accessories.hjson
@@ -1,404 +1,617 @@
StaminaItem: {
- DisplayName: Stamina Item
- Tooltip: ""
+ DisplayName: è€åŠ›æµ‹è¯•ç‰©å“
+ Tooltip: "å¼€å‘者物å“"
}
EnergyBand: {
- DisplayName: Energy Band
- Tooltip: ""
+ DisplayName: 能é‡ç»·å¸¦
+ Tooltip: "å‡å°‘25%体力消耗"
}
BloodGlucoseMonitor: {
- DisplayName: Blood Glucose Monitor
- Tooltip: ""
+ DisplayName: 血糖仪
+ Tooltip: "显示饥饿值"
}
OsmoticPressureMonitor: {
- DisplayName: Osmotic Pressure Monitor
- Tooltip: ""
+ DisplayName: 渗é€åŽ‹æµ‹å®šä»ª
+ Tooltip: "显示渴度"
}
PlayerPenetrationTest: {
- DisplayName: Player Penetration Test
- Tooltip: ""
+ DisplayName: çŽ©å®¶ç©¿é€æµ‹è¯•物å“
+ Tooltip: "å¼€å‘者物å“"
}
BurningFrozenHeart: {
- DisplayName: Burning Frozen Heart
- Tooltip: ""
+ DisplayName: 霜ç«ä¹‹å¿ƒ
+ Tooltip: "å…疫多数冷系伤害并å‘出霜ç«çš„å…‰"
}
PearlOfCyan: {
- DisplayName: Pearl Of Cyan
- Tooltip: ""
+ DisplayName: æ¾æ™¯çƒ
+ Tooltip: "æš´å‡»æ—¶é™„åŠ 4锿³•伤害的æ¾é’ˆå助攻击"
}
SnowPineLockBox: {
- DisplayName: Snow Pine Lock Box
- Tooltip: ""
+ DisplayName: 有æ¾é¦™çš„é“ç›’
+ Tooltip: "å¬å”¤æ¾æ ‘之çµå助作战"
}
TuskLace: {
- DisplayName: Tusk Lace
- Tooltip: ""
+ DisplayName: ç 牙项链
+ Tooltip:
+ '''
+ 盔甲穿é€å¢žåŠ 5\nä¼¤å®³å’Œæš´å‡»å¢žåŠ 5%
+ 一颗ç 牙被从猛兽嘴里打了下æ¥,ä½ åˆæ•²ä¸‹äº†ä¸Šé¢çš„一å°éƒ¨åˆ†
+ '''
}
FireflyBorageBadge: {
- DisplayName: Firefly Borage Badge
- Tooltip: ""
+ DisplayName: æµè¤é»‘花胸ç«
+ Tooltip: "伤害+6%,速度+15%ï¼Œè…æª€å·¨è›¾å˜åœ¨æ—¶æœ‰ç‰¹æ®Šæ•ˆæžœ"
}
MothEye: {
- DisplayName: Moth Eye
- Tooltip: ""
+ DisplayName: 蛾眼
+ Tooltip: "å¬å”¤ä¼¤å®³+6%,å¬å”¤æ ä½+1,哨兵æ ä½+1,对æµè¤ç³»åˆ—æ¦å™¨æœ‰ç‰¹æ®Šæ•ˆæžœ"
}
BlueflowerBra: {
- DisplayName: Blueflower Bra
+ DisplayName: è“花黑内衣
Tooltip: ""
}
BlueflowerCap: {
- DisplayName: Blueflower Cap
+ DisplayName: è“花黑阔边帽
Tooltip: ""
}
BlueGel: {
- DisplayName: Blue Gel
- Tooltip: ""
+ DisplayName: è“æ˜Ÿå‡èƒ¶
+ Tooltip: "+4é”力回å¤å’Œ30锿³•上é™"
}
CorruptEye: {
- DisplayName: Corrupt Eye
- Tooltip: ""
+ DisplayName: è…化之眼
+ Tooltip: "防御+5,伤害+4%,å…ç–«å’’ç«ï¼Œå—击åŽè¿¸å‘出若干咒ç«çƒ"
}
DukeTooth: {
- DisplayName: Duke Tooth
- Tooltip: ""
+ DisplayName: 猪龙鱼ç 牙åŠå
+ Tooltip: "+12盔甲穿é€"
}
GoldLiquidPupil: {
- DisplayName: Gold Liquid Pupil
- Tooltip: ""
+ DisplayName: çµæ¶²çž³å”
+ Tooltip: "å—击åŽç”Ÿæˆçµæ¶²ä¹‹çޝ"
}
GreenGel: {
- DisplayName: Green Gel
- Tooltip: ""
+ DisplayName: 绿心å‡èƒ¶
+ Tooltip: "+4生命回å¤å’Œ30生命上é™"
}
JungleVitamin: {
- DisplayName: Jungle Vitamin
- Tooltip: ""
+ DisplayName: 丛林维生ç´
+ Tooltip: "+50生命上é™"
}
Odd8Ring: {
- DisplayName: Odd8 Ring
- Tooltip: ""
+ DisplayName: 诡8指环
+ Tooltip: "啿¬¡é€ æˆçš„æœ€ä½Žä¼¤å®³å˜ä¸º8"
}
RedGel: {
- DisplayName: Red Gel
- Tooltip: ""
+ DisplayName: 红尖å‡èƒ¶
+ Tooltip: "暴击率+6%,暴击伤害+9%"
}
SilverWing: {
- DisplayName: Silver Wing
- Tooltip: ""
+ DisplayName: 银翼è¯ç«
+ Tooltip: "暴击伤害+8%,3ç§’ä¸ä½¿ç”¨æ¦å™¨åŽä¼¤å®³+40%"
}
WalnutClip: {
- DisplayName: Walnut Clip
- Tooltip: ""
+ DisplayName: 胡桃夹å
+ Tooltip: "暴击伤害+16%ï¼Œç”Ÿå‘½å€¼ä½ŽäºŽä¸€åŠæ—¶å¢žåŠ æ‰€æœ‰ä¼¤å®³ï¼Œç”Ÿå‘½å€¼è¶Šä½Žå¹…åº¦è¶Šå¤§"
}
BlueTorchFlower: {
- DisplayName: Blue Torch Flower
- Tooltip: ""
+ DisplayName: ç¿ è“冰炬
+ Tooltip:
+ '''
+ å¢žåŠ 20é”力上é™
+ 命䏿•Œäººå›žå¤2é”力,有0.2秒冷å´
+ 'ç«ç‚¬èŠ±çš„ä¸€ä¸ªå˜ç§'
+ '''
}
CyanBranch: {
- DisplayName: Cyan Branch
- Tooltip: ""
+ DisplayName: 一æŸå¤©é’
+ Tooltip:
+ '''
+ å—击åŽ10ç§’å¢žåŠ 8é—ªé¿èƒ½åŠ›
+ '它å分åšç¡¬ï¼Œä½†ä¹Ÿå¾ˆè„†å¼±'
+ '''
}
CyanPedal: {
- DisplayName: Cyan Pedal
- Tooltip: ""
+ DisplayName: 四瓣ç‰ç’ƒ
+ Tooltip:
+ '''
+ é—ªé¿èƒ½åŠ›å¢žåŠ 4
+ 'å°‘çš„é‚£ä¸€ç“£åŒ–ä½œä½ çš„å‹‡æ°”'
+ '''
}
DarkHat: {
- DisplayName: Dark Hat
- Tooltip: ""
+ DisplayName: 罂粟花å 饰
+ Tooltip:
+ '''
+ å¢žåŠ 20é”力上é™
+ æš´å‡»çŽ‡å¢žåŠ 4%,æš´å‡»ä¼¤å®³å¢žåŠ 12
+ '除用于战斗和装饰ä¸å»ºè®®ä½¿ç”¨'
+ '''
}
GoldRound: {
- DisplayName: Gold Round
- Tooltip: ""
+ DisplayName: 金ç›è½®ç›˜
+ Tooltip:
+ '''
+ +7防御,+7%伤害
+ 'ä¼ ç»Ÿçš„æ³°æ‹‰äººé€šå¸¸é…æˆ´å®ƒæ¥ä¿æŒå¥åº·'
+ '''
}
HotPinkCrown: {
- DisplayName: Hot Pink Crown
- Tooltip: ""
+ DisplayName: 活化éƒé‡‘香
+ Tooltip:
+ '''
+ æš´å‡»ä¼¤å®³å¢žåŠ (最大生命值*5%)%
+ 'ç»è¿‡é£Žä¹‹ç²¾åŽçš„催化,它将对生命力åšå‡ºå应'
+ '''
}
LightPurplePen: {
- DisplayName: Light Purple Pen
- Tooltip: ""
+ DisplayName: 紫豪ä¸å±±å…”
+ Tooltip:
+ '''
+ ä¼¤å®³ã€æš´å‡»çŽ‡å’Œè¿‘æˆ˜æ”»é€Ÿå„å¢žåŠ 7%
+ '没有任何兔å在制作过程ä¸å—到伤害'
+ '''
}
ManyWhiteFlower: {
- DisplayName: Many White Flower
- Tooltip: ""
+ DisplayName: 白星锦çƒ
+ Tooltip:
+ '''
+ è¿‘æˆ˜æ”»é€Ÿå¢žåŠ 8%,è¿‘æˆ˜ä¼¤å®³å¢žåŠ 8%
+ 'ä½ ä¸æƒ³è®©è¿™äº›ç¥žå¥‡åˆå¯çˆ±çš„花被æŸå'
+ '''
}
OrangeCrown: {
- DisplayName: Orange Crown
- Tooltip: ""
+ DisplayName: åšéŸ§éƒé‡‘香
+ Tooltip:
+ '''
+ 防御力+(最大生命值*3%)%
+ '埃俄罗斯ç¥ç¦è¿‡çš„éƒé‡‘香,结构强度出奇的高'
+ '''
}
OrangeStick: {
- DisplayName: Orange Stick
- Tooltip: ""
+ DisplayName: åšæ©™ç‹¼å°¾
+ Tooltip:
+ '''
+ å—击åŽ3秒获得5防御力和击退å…ç–«
+ '与大多数è‰ä¸åŒ,它在狂风ä¸åšæŒºè€Œä¸æŠ˜è…°'
+ '''
}
PinkFourPedal: {
- DisplayName: Pink Four Pedal
- Tooltip: ""
+ DisplayName: 四命轮回
+ Tooltip:
+ '''
+ æœ€å¤§ç”Ÿå‘½å€¼å¢žåŠ 40
+ 'æ®è¯´å—伤的动物会去åƒå®ƒæ¥ç–—伤...事实确实如æ¤,但好åƒå¯¹äººæ•ˆæžœä¸å¤§'
+ '''
}
PurpleBall: {
- DisplayName: Purple Ball
- Tooltip: ""
+ DisplayName: 紫绣çƒåŠå
+ Tooltip:
+ '''
+ 命ä¸èº«å‘¨çš„æ•Œäººä¼šé‡Šæ”¾ç´«è‰²èŠ±ç“£çˆ†ç‚¸
+ èŠ±ç“£ä¼¤å®³éšæ”»å‡»çš„伤害增åŠ
+ 有0.5秒冷å´
+ '愤怒紫绣çƒ'
+ '''
}
PurpleReedHalo: {
- DisplayName: Purple Reed Halo
- Tooltip: ""
+ DisplayName: 紫苇花å†
+ Tooltip:
+ '''
+ 生命上é™å¢žåŠ 30
+ é”力上é™å¢žåŠ 40
+ '好闻åˆå¥½çœ‹'
+ '''
}
RedTriangle: {
- DisplayName: Red Triangle
- Tooltip: ""
+ DisplayName: 三尖红ç‹
+ Tooltip:
+ '''
+ æš´å‡»ä¼¤å®³å¢žåŠ 18%
+ '在泰拉文化ä¸,这是一ç§å…·æœ‰æ”»å‡»æ€§çš„形状'
+ '''
}
SilverCupFlower: {
- DisplayName: Silver Cup Flower
- Tooltip: ""
+ DisplayName: 皇家酒æ¯
+ Tooltip:
+ '''
+ +8防御
+ 生命上é™å¢žåŠ 20
+ 'æ›¾æœ‰ä¸€ä½æ®‹æš´çš„国王真的å°è¯•拿它当酒æ¯,他一滴也没å–上'
+ '''
}
ThreeColorCrown: {
- DisplayName: Three Color Crown
- Tooltip: ""
+ DisplayName: 三色花环
+ Tooltip:
+ '''
+ 击䏿•ŒäººåŽéšæœºèŽ·å¾—ä»¥ä¸‹ä¸‰ç§æ•ˆæžœä¹‹ä¸€,æŒç»7ç§’
+ 红:ä¼¤å®³å¢žåŠ 22%ï¼Œæš´å‡»çŽ‡å¢žåŠ 11%
+ ç´«:å…ç–«ç»å¤§å¤šæ•°å‡ç›Šæ•ˆæžœ
+ é”力上é™å¢žåŠ 300
+ 有30秒CD
+ '求别太幸è¿'
+ '''
}
WhiteCrown: {
- DisplayName: White Crown
- Tooltip: ""
+ DisplayName: 希望之花
+ Tooltip:
+ '''
+ å¥”è·‘é€Ÿåº¦å¢žåŠ (生命上é™*0.2%)
+ '一æžç´ 白的éƒé‡‘香,åƒåœ¨æ‚¼å¿µ...'
+ '''
}
WhitePedal: {
- DisplayName: White Pedal
- Tooltip: ""
+ DisplayName: 光纱之瓣
+ Tooltip:
+ '''
+ é—ªé¿èƒ½åŠ›å¢žåŠ 2
+ æš´å‡»çŽ‡å¢žåŠ 4%
+ '它是如æ¤è½»è–„'
+ '''
}
WhiteWoodFlower: {
- DisplayName: White Wood Flower
- Tooltip: ""
+ DisplayName: 银耳花
+ Tooltip:
+ '''
+ å¬å”¤æ ä½å¢žåŠ 2
+ '奇妙的共生关系'
+ '''
}
YellowBellFlower: {
- DisplayName: Yellow Bell Flower
- Tooltip: ""
+ DisplayName: 金簇铃兰
+ Tooltip:
+ '''
+ ä¼¤å®³å¢žåŠ (20%防御力)%
+ '稀有åˆå¥½çœ‹'
+ '''
}
CrystalSkull: {
- DisplayName: Crystal Skull
- Tooltip: ""
+ DisplayName: 水晶颅骨
+ Tooltip:
+ '''
+ è®©ä½ å®Œå…¨ç†è§£é”æ³•ä¹¦ä¸æ‰€è®°è½½çš„æ³•术,它强大得令人胆寒
+ '以å‰çš„ç”¨æ³•å°±åƒæ‹¿æžªæ†åå½“æ£æ£’敲人'
+ '''
}
AnemoShell: {
- DisplayName: Anemo Shell
- Tooltip: ""
+ DisplayName: æ°”å…ƒç´ é˜²æ’žå£³
+ Tooltip:
+ '''
+ é到跌è½ä¼¤å®³ä¹‹å‰ï¼Œå°†çީ家ç¨ç¨å¼¹èµ·ï¼ŒæŠµæ¶ˆæ¤æ¬¡ä¼¤å®³
+ æ¤æ•ˆæžœå†·å´60ç§’
+ '''
}
BloodTearCrystalCrown: {
- DisplayName: Blood Tear Crystal Crown
- Tooltip: ""
+ DisplayName: 滴血泪石å†
+ Tooltip:
+ '''
+ 生命上é™+60
+ 生命值>84%æ—¶é¢å¤–å¢žåŠ 1生命回å¤
+ '''
}
CelesteStoneWaistPendant: {
- DisplayName: Celeste Stone Waist Pendant
- Tooltip: ""
+ DisplayName: å¤©è“æ™¶çŸ³æŒ‚å
+ Tooltip:
+ '''
+ 法力上é™+30
+ 法力值处于40%~60%æ—¶å¢žåŠ 2锿³•回å¤
+ '''
}
CelticSeal: {
- DisplayName: Celtic Seal
- Tooltip: ""
+ DisplayName: 凯尔特å°å°
+ Tooltip: "æ¯å—到3次超过6点的伤害获得15点治疗"
}
ConcealSpell: {
- DisplayName: Conceal Spell
- Tooltip: ""
+ DisplayName: éšåŒ¿ç¬¦ç®“
+ Tooltip:
+ '''
+ 陿¢æ—¶æ¯å¸§å……能1点,移动时0.05
+ 能é‡è¾¾åˆ°600时获得"éšåŒ¿",éšå½¢ä¸”å…疫下一次攻击
+ 但是å—击åŽèƒ½é‡æ¸…é›¶
+ '''
}
CyanVineRing: {
- DisplayName: Cyan Vine Ring
- Tooltip: ""
+ DisplayName: å¤é’缎指环
+ Tooltip: "暴击率+4%,å—到伤害åŽ1ç§’å†…è‹¥é€ æˆä¼¤å®³åˆ™å†+4%,æŒç»15ç§’"
}
ForsakenBoots: {
- DisplayName: Forsaken Boots
- Tooltip: ""
+ DisplayName: 失è½ä¹‹é´
+ Tooltip:
+ '''
+ 8%移速æå‡
+ å…许玩家奔跑
+ '''
}
FragmentsOfWreckage: {
- DisplayName: Fragments Of Wreckage
- Tooltip: ""
+ DisplayName: 残骸碎片
+ Tooltip:
+ '''
+ å½“ç”Ÿå‘½å€¼ä¸æ»¡æ—¶ï¼Œæ ¹æ®æŸå¤±çš„生命值æé«˜å±žæ€§ï¼ŒæŸå¤±400生命时达到最大效果,最大效果如下
+ +10% 近战速度
+ +10% 伤害
+ +12 防御
+ +15% 挖矿速度
+ '''
}
FuneraryGoods: {
- DisplayName: Funerary Goods
- Tooltip: ""
+ DisplayName: 陪葬å“
+ Tooltip: "å‡»æ€æ•Œäººæ—¶ï¼Œ1/8概率立刻æ¢å¤100é”力"
}
FurnaceIronGloves: {
- DisplayName: Furnace Iron Gloves
- Tooltip: ""
+ DisplayName: ç†”ç‚‰é“æ‰‹å¥—
+ Tooltip: "法术伤害附带5%伤害的浊燃æŸä¼¤"
}
IstafelsSunfireGrasp: {
- DisplayName: Istafels Sunfire Grasp
- Tooltip: ""
+ DisplayName: 伊斯塔裴尔的炎阳之æ¡
+ Tooltip:
+ '''
+ +11%锿³•伤害
+ +5%暴击率
+ 法术伤害附带5%伤害的浊燃æŸä¼¤
+ æ”»å‡»æœ‰æ¦‚çŽ‡åˆ›é€ ä¸€ä¸ªç†”æ¸£ç«çƒæ¼‚浮于玩家身边,法术攻击å¯ä¸ºç†”渣蓄能
+ 达到一定储能的熔渣将自动射出ç«çƒæ”»å‡»
+ 当计é‡è¡¨è“„力完æˆåŽä¸‹ä¸€æ¬¡æ”»å‡»å°†æŽ·å‡ºè¿¸å‘çš„ç†”æ¸£ï¼Œé€ æˆå¤šæ®µçš„25æ— è§†é˜²å¾¡ä¸Žå‡ä¼¤çš„çœŸå®žä¼¤å®³ï¼Œå¹¶é€ æˆ16秒“烧焦â€debuff。
+ 冷崿—¶é—´150s
+ *çƒ§ç„¦ï¼šé€ æˆ18dps伤害并å‡å°‘ç›®æ ‡11%防御,ä¸ä½ŽäºŽ0
+ ä¼ è¯´æŠ€èƒ½ï¼šæŒ‰ä¸‹<å¿«æ·é”®>叿”¶é™„近所有的浊燃æŸä¼¤ï¼Œç«‹åˆ»ç»“算所有伤害并对被å‡ç›Šçš„ç›®æ ‡ä¼¤å®³æå‡è‡³150%。æŒç»20s,
+ boss战期间åªèƒ½ä½¿ç”¨ä¸€æ¬¡
+ '''
}
JellyBallInhibitor: {
- DisplayName: Jelly Ball Inhibitor
- Tooltip: ""
+ DisplayName: çƒå†»æŠ‘制剂
+ Tooltip: "玩家对çƒå†»æ•Œäººé€ æˆçš„伤害æé«˜60%,å—到çƒå†»ç±»æ•Œäººçš„æŽ¥è§¦ä¼¤å®³é™ä½Žä¸º75%"
}
LampWoodPollenBottle: {
- DisplayName: Lamp Wood Pollen Bottle
- Tooltip: ""
+ DisplayName: ç¯æœ¨èŠ±ç²‰ç“¶
+ Tooltip: "å…许三段跳,åŒç±»é¥°å“å¯å åŠ "
}
ManaThermalPipeline: {
- DisplayName: Mana Thermal Pipeline
- Tooltip: ""
+ DisplayName: 奥术çƒèƒ½ç®¡çº¿
+ Tooltip: "+5%锿³•伤害,+4é”力å†ç”Ÿ"
}
RecoveryBand: {
- DisplayName: Recovery Band
- Tooltip: ""
+ DisplayName: æ¢å¤æ‰‹çޝ
+ Tooltip: "å—到ä¸ä½ŽäºŽ5ç‚¹çš„ä¼¤å®³æ—¶ï¼ŒåŒæ—¶æ¢å¤å°‘é‡ç”Ÿå‘½å€¼å’Œé”力值"
}
RingOfMatter: {
- DisplayName: Ring Of Matter
- Tooltip: ""
+ DisplayName: 物质戒指
+ Tooltip:
+ '''
+ è£…å¤‡æ—¶ï¼Œæ ¹æ®çŽ©å®¶è£…å¤‡çž¬é—´æ‹¥æœ‰çš„é’±å¸æ•°é‡åŸºäºŽæ•ˆæžœï¼š
+ æé«˜ä¼¤å®³ï¼Œæé«˜é˜²å¾¡åŠ›ï¼Œä½†æ˜¯ç”Ÿå‘½ä¸Šé™å‡å°‘
+ 钱越多效果越强,5铂金达到上é™
+ '''
}
ShacklesBall: {
- DisplayName: Shackles Ball
- Tooltip: ""
+ DisplayName: 带çƒè„šé•£
+ Tooltip:
+ '''
+ å¢žåŠ 10%伤害å‡å…,但是速度ã€è·³è·ƒé€Ÿåº¦å‡å°‘15%,跳跃高度é™ä½Ž7%ï¼›
+ å…疫缓慢
+ '''
}
SkullCollection: {
- DisplayName: Skull Collection
- Tooltip: ""
+ DisplayName: 头骨收è—
+ Tooltip: "玩家近身å˜åœ¨æ•Œæ€ªæ—¶ï¼ŒçŽ©å®¶èŽ·å¾—é”力å†ç”Ÿ"
}
SpicyShield: {
- DisplayName: Spicy Shield
- Tooltip: ""
+ DisplayName: 尖刺盾牌
+ Tooltip:
+ '''
+ 防御+4
+ 伤害+4%
+ å—到伤害åŽèŽ·å¾—30ç§’çš„è†æ£˜æ•ˆæžœ
+ '''
}
TelescopicPlatformAlpha: {
- DisplayName: Telescopic Platform Alpha
- Tooltip: ""
+ DisplayName: 伸缩平å°Î±
+ Tooltip: "åœ¨åœ°é¢æŒ‰Wå…许å‡èµ·ï¼Œå‡èµ·åŽæŒ‰S下é™ï¼Œä¸æ“ä½œä¿æŒæ‚¬åœã€‚最大高度15æ ¼"
}
TelescopicPlatformBeta: {
- DisplayName: Telescopic Platform Beta
- Tooltip: ""
+ DisplayName: 伸缩平å°Î²
+ Tooltip: "åœ¨åœ°é¢æŒ‰Wå…许å‡èµ·ï¼Œå‡èµ·åŽæŒ‰S下é™ï¼Œä¸æ“ä½œä¿æŒæ‚¬åœã€‚最大高度45æ ¼"
}
HeatEmblem: {
- DisplayName: Heat Emblem
- Tooltip: ""
+ DisplayName: çƒèƒ½å‹‹ç«
+ Tooltip:
+ '''
+ +2生命å†ç”Ÿ
+ 但是å—到伤害时,获得“ç€ç«äº†â€5ç§’
+ '''
}
HotAirBalloon: {
- DisplayName: Hot Air Balloon
- Tooltip: ""
+ DisplayName: çƒæ°”çƒ
+ Tooltip: "å¢žåŠ è·³è·ƒé«˜åº¦ï¼Œç«ç„°ç²’å尾迹"
}
MelterGear: {
- DisplayName: Melter Gear
- Tooltip: ""
+ DisplayName: çƒç†”齿轮
+ Tooltip: "é€ æˆä¼¤å®³æ—¶ï¼Œå¯¹ç”Ÿç‰©é€ æˆâ€œç€ç«äº†â€5秒,但在攻击带有“ç€ç«äº†â€çš„生物时,有33%çš„æ¦‚çŽ‡å¯¹è‡ªå·±é€ æˆâ€œç‡ƒçƒ§â€5秒,在æˆåŠŸè§¦å‘åŽè€…åŽï¼Œè¿›å…¥å†·å´15ç§’"
}
MoltenCore: {
- DisplayName: Molten Core
- Tooltip: ""
+ DisplayName: ç†”ç«æ ¸å¿ƒ
+ Tooltip:
+ '''
+ 当玩家处于“ç€ç«äº†â€ã€â€œç‡ƒçƒ§â€ã€â€œè¯…å’’ç„°â€çš„æ•ˆæžœçŠ¶æ€æ—¶
+ æé«˜5%伤害å‡å…ã€5防御ã€5%暴击ã€5%伤害ã€5%速度ã€5%跳跃速度
+ '''
}
ThermalConductor: {
- DisplayName: Thermal Conductor
- Tooltip: ""
+ DisplayName: çƒèƒ½ä¼ 导器
+ Tooltip: "æ¯60帧会进行一次判æ–,若玩家的é”力ä¸é«˜äºŽæœ€å¤§é”力的20%,有33%çš„æ¦‚çŽ‡å¯¹çŽ©å®¶é€ æˆâ€œè¯…å’’ç„°â€3ç§’å¹¶æ¢å¤100é”力值"
}
AntiCorrosiveSole: {
- DisplayName: Anti Corrosive Sole
- Tooltip: ""
+ DisplayName: 抗è…蚀鞋底
+ Tooltip:
+ '''
+ +5%移速
+ å…ç–«è…蚀
+ '''
}
CorrodedPearl: {
- DisplayName: Corroded Pearl
- Tooltip: ""
+ DisplayName: 被è…蚀的çç
+ Tooltip:
+ '''
+ å»¶é•¿æ°´ä¸‹å‘¼å¸æ—¶é—´50%
+ å°å¹…度æå‡åœ¨æ°´ä¸çš„移动速度
+ +5%å¬å”¤ä¼¤å®³
+ '''
}
EmptyFowlbeast: {
- DisplayName: Empty Fowlbeast
- Tooltip: ""
+ DisplayName: 空羽兽
+ Tooltip:
+ '''
+ +1仆从数é‡ï¼Œä»†ä»Žå¯é¢å¤–é€ æˆç‰åŒäºŽçŽ©å®¶æœ€å¤§é”æ³•值7%çš„é”æ³•伤害
+ 玩家é¢å¤–å—到20%伤害
+ '''
}
ForestMino: {
- DisplayName: Forest Mino
- Tooltip: ""
+ DisplayName: 森之蓑衣
+ Tooltip:
+ '''
+ 4防御
+ 在è‹è‹”帘幕时移动速度+25%,且敌人更难å‘现ä½
+ '''
}
GuppyShell: {
- DisplayName: Guppy Shell
- Tooltip: ""
+ DisplayName: æ ¼æ™®èžºå¤–å£³
+ Tooltip:
+ '''
+ 2防御
+ 站立ä¸åŠ¨æ—¶,获得10%å‡ä¼¤ï¼Œ+5%伤害,-5%移速
+ '''
}
HardenedWitherbarkHeart: {
- DisplayName: Hardened Witherbark Heart
- Tooltip: ""
+ DisplayName: 硬化枯木心è„
+ Tooltip:
+ '''
+ 10防御
+ -40%冲刺速度,-10%移速
+ 给予硬化皮肤增益,使得å—到的第一次伤害-90%,但是在å—击åŽï¼Œç»™äºˆ10ç§’ç ´ç»½æ•ˆæžœï¼Œé¢å¤–å—到50%伤害
+ ç ´ç»½æ•ˆæžœç»“æŸï¼Œé‡æ–°ç»™äºˆç¡¬åŒ–皮肤。
+ '''
}
LivingWoodplate: {
- DisplayName: Living Woodplate
- Tooltip: ""
+ DisplayName: 活木甲
+ Tooltip:
+ '''
+ +4防御
+ 接触水时获得+8生命å†ç”Ÿï¼Œ40最大生命值,æŒç»30ç§’
+ '''
}
OrfeoBoots: {
- DisplayName: Orfeo Boots
- Tooltip: ""
+ DisplayName: å¥¥è²æ¬§ä¹‹é´
+ Tooltip:
+ '''
+ å¯å¥”跑,速度æå‡12%
+ 在战斗ä¸è·‘得更快并跳得更高
+ '''
}
RadialCarapace: {
- DisplayName: Radial Carapace
- Tooltip: ""
+ DisplayName: 放射状甲壳
+ Tooltip:
+ '''
+ 4防御,在水下时é¢å¤–æä¾›4防御
+ é™ä½Ž5%移速,但是在水下的移速æå‡35%
+ '''
}
TheGreenSolar: {
- DisplayName: The Green Solar
- Tooltip: ""
+ DisplayName: 绿阳之石
+ Tooltip:
+ '''
+ +20生命上é™
+ å—到致命伤害åŽä¸ä¼šæ»åŽ»è€Œæ˜¯è¿›å…¥æ¶…æ§ƒçŠ¶æ€ã€‚移速在3秒内衰å‡ä¸º0å¹¶è¿›å…¥æ— æ•Œï¼Œæ¯ç§’回å¤5点最大生命值
+ 在涅槃期间,散å‘太阳光辉ç¼çƒ§é™„è¿‘çš„æ•Œäººï¼Œé€ æˆâ€œç€ç«äº†â€
+ 冷崿—¶é—´600ç§’
+ '''
}
ThornTurtleShell: {
- DisplayName: Thorn Turtle Shell
- Tooltip: ""
+ DisplayName: è†æ£˜é¾Ÿå£³
+ Tooltip:
+ '''
+ +6防御
+ ç»™äºˆè†æ£˜æ•ˆæžœ
+ -7%移速
+ -10%冲刺速度
+ +5%伤害å‡å…
+ '''
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Ammo.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Ammo.hjson
index e0268f338..2d242ef0a 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Ammo.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Ammo.hjson
@@ -1,9 +1,9 @@
CyanVineBullet: {
- DisplayName: Cyan Vine Bullet
+ DisplayName: é’缎弹
Tooltip: ""
}
HuskburstBullet: {
- DisplayName: Huskburst Bullet
- Tooltip: ""
+ DisplayName: 果壳弹
+ Tooltip: "击ä¸åŽçˆ†è£‚出çŸè·ç¦»çš„å°åž‹åå¼¹"
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Armor.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Armor.hjson
index bb5a6531b..bd1438126 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Armor.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Armor.hjson
@@ -35,216 +35,222 @@ DevilHeartLeggings: {
}
FireflywoodBreastplate: {
- DisplayName: Fireflywood Breastplate
+ DisplayName: æµè¤æ¿ç”²
Tooltip: ""
}
FireflywoodHelmet: {
- DisplayName: Fireflywood Helmet
+ DisplayName: æµè¤å¤´ç›”
Tooltip: ""
}
FireflywoodLeggings: {
- DisplayName: Fireflywood Leggings
+ DisplayName: æµè¤æŠ¤èƒ«
Tooltip: ""
}
BlueflowerDress: {
- DisplayName: Blueflower Dress
+ DisplayName: è“花黑裙
Tooltip: ""
}
ValiantBreastplate: {
- DisplayName: Valiant Breastplate
- Tooltip: ""
+ DisplayName: 勇者胸甲
+ Tooltip: "这套盔甲往往是æ¥åˆ°å¤©ç©¹é•‡çš„人们的第一笔报酬"
}
ValiantHelmet: {
- DisplayName: Valiant Helmet
- Tooltip: ""
+ DisplayName: 勇者头盔
+ Tooltip: "这套盔甲往往是æ¥åˆ°å¤©ç©¹é•‡çš„人们的第一笔报酬"
}
ValiantLeggings: {
- DisplayName: Valiant Leggings
- Tooltip: ""
+ DisplayName: 勇者护胫
+ Tooltip: "这套盔甲往往是æ¥åˆ°å¤©ç©¹é•‡çš„人们的第一笔报酬"
}
TwilightWoodBreastplate: {
- DisplayName: Twilight Wood Breastplate
+ DisplayName: 暮桉木æ¿ç”²
Tooltip: ""
}
TwilightWoodHelmet: {
- DisplayName: Twilight Wood Helmet
+ DisplayName: 暮桉木头盔
Tooltip: ""
}
TwilightWoodLeggings: {
- DisplayName: Twilight Wood Leggings
+ DisplayName: 暮桉木护胫
Tooltip: ""
}
ConventionalEquipment: {
- DisplayName: Conventional Equipment
- Tooltip: ""
+ DisplayName: æ ‡å‡†æŠ¤å…·
+ Tooltip: "å…·å¤‡ä¸€å®šä¿æŠ¤æ€§ï¼Œåªæ˜¯ç©¿ç€æ¯«æ— 舒适度å¯è¨€"
}
SafetyHelmets: {
- DisplayName: Safety Helmets
- Tooltip: ""
+ DisplayName: 安全头盔
+ Tooltip: "批é‡ç”Ÿäº§çš„å¤´ç›”ï¼Œè¿‡é•¿çš„ä»“å‚¨å‘¨æœŸä½¿ææ–™è€åŒ–"
}
StandardLeggings: {
- DisplayName: Standard Leggings
- Tooltip: ""
+ DisplayName: 制å¼é´å
+ Tooltip: "åªæœ‰ä¸¤ä¸ªç æ•°ï¼Œä¼¼ä¹Žæ— æ³•é€‚é…æ‰€æœ‰äºº"
}
RockGreaves: {
- DisplayName: Rock Greaves
+ DisplayName: 岩甲护腿
Tooltip: ""
}
RockHelmet: {
- DisplayName: Rock Helmet
+ DisplayName: 岩甲头盔
Tooltip: ""
}
RockPlateMail: {
- DisplayName: Rock Plate Mail
+ DisplayName: 岩甲æ¿ç”²
Tooltip: ""
}
ConcentratingJacket: {
- DisplayName: Concentrating Jacket
+ DisplayName: 充能夹克
Tooltip: ""
}
ExplorationHelmet: {
- DisplayName: Exploration Helmet
+ DisplayName: 探照头盔
Tooltip: ""
}
OvineHairpin: {
- DisplayName: Ovine Hairpin
+ DisplayName: ç¯ç 头饰
Tooltip: ""
}
ShadowlessBoots: {
- DisplayName: Shadowless Boots
+ DisplayName: æ— å½±é´å
Tooltip: ""
}
LampWoodBreastplate: {
- DisplayName: Lamp Wood Breastplate
+ DisplayName: ç¯æœ¨èƒ¸ç”²
Tooltip: ""
}
LampWoodHelmet: {
- DisplayName: Lamp Wood Helmet
+ DisplayName: ç¯æœ¨å¤´ç›”
Tooltip: ""
}
LampWoodLeggings: {
- DisplayName: Lamp Wood Leggings
+ DisplayName: ç¯æœ¨æŠ¤è…¿
Tooltip: ""
}
JellyBallBathingCap: {
- DisplayName: Jelly Ball Bathing Cap
+ DisplayName: çƒå†»å¸½
Tooltip: ""
}
CyanBreastplate: {
- DisplayName: Cyan Breastplate
+ DisplayName: é’缎甲
Tooltip: ""
}
CyanHeavylet: {
- DisplayName: Cyan Heavylet
+ DisplayName: é’缎头盔
Tooltip: ""
}
CyanLeggings: {
- DisplayName: Cyan Leggings
+ DisplayName: é’缎鞋
Tooltip: ""
}
CyanWarhelm: {
- DisplayName: Cyan Warhelm
+ DisplayName: é’缎战盔
Tooltip: ""
}
BloodDrenchedRobe: {
- DisplayName: Blood Drenched Robe
- Tooltip: ""
+ DisplayName: æ²è¡€é•¿è¢
+ Tooltip:
+ '''
+ “他们用宿主鲜活的é”è„æ¸©å…»ç»‡å…½ï¼Œå†ç”¨ç»‡å…½ç¼–织鲜红的锦缎â€
+ '''
}
BloodStainedVeil: {
- DisplayName: Blood Stained Veil
- Tooltip: ""
+ DisplayName: 染血纱帽
+ Tooltip:
+ '''
+ ä¼ è¯´è™½æ˜¯å¦‚æ¤ï¼Œçœ¼å‰çš„è¡£è£…é™¤äº†æ¯”è¾ƒç ´æ—§ï¼Œå’Œæ³•å¸ˆé•¿è¢å¹¶æ— 二致
+ '''
}
AuburnBoots: {
- DisplayName: Auburn Boots
- Tooltip: ""
+ DisplayName: 金棕é´
+ Tooltip: "é£žæ£æ»åŽï¼Œå”¯å‰©ä¸€æ”¯ç©ºç®¡ï¼Œç”šè‡³æ‰¾ä¸åˆ°å®ƒçš„é”è„......ä¸è¿‡è¿™å…·å¤–壳还挺好看的"
}
AuburnBreastplate: {
- DisplayName: Auburn Breastplate
- Tooltip: ""
+ DisplayName: 金棕战甲
+ Tooltip: "é£žæ£æ»åŽï¼Œå”¯å‰©ä¸€æ”¯ç©ºç®¡ï¼Œç”šè‡³æ‰¾ä¸åˆ°å®ƒçš„é”è„......ä¸è¿‡è¿™å…·å¤–壳还挺好看的"
}
AuburnHoodie: {
- DisplayName: Auburn Hoodie
- Tooltip: ""
+ DisplayName: 金棕兜帽
+ Tooltip: "é£žæ£æ»åŽï¼Œå”¯å‰©ä¸€æ”¯ç©ºç®¡ï¼Œç”šè‡³æ‰¾ä¸åˆ°å®ƒçš„é”è„......ä¸è¿‡è¿™å…·å¤–壳还挺好看的"
}
WitherbarkBreastPlate: {
- DisplayName: Witherbark Breast Plate
+ DisplayName: 枯木胸甲
Tooltip: ""
}
WitherbarkHelmet: {
- DisplayName: Witherbark Helmet
+ DisplayName: 枯木头盔
Tooltip: ""
}
WitherbarkLeggings: {
- DisplayName: Witherbark Leggings
+ DisplayName: 枯木护腿
Tooltip: ""
}
RuinLeggings: {
- DisplayName: Ruin Leggings
+ DisplayName: 归墟护胫
Tooltip: ""
}
RuinMagicRobe: {
- DisplayName: Ruin Magic Robe
+ DisplayName: 归墟咒è¢
Tooltip: ""
}
RuinMask: {
- DisplayName: Ruin Mask
+ DisplayName: 归墟é¢ç½©
Tooltip: ""
}
MolluscsLeggings: {
- DisplayName: Molluscs Leggings
+ DisplayName: 软体足部
Tooltip: ""
}
MossyMolluscsHelmet: {
- DisplayName: Mossy Molluscs Helmet
+ DisplayName: 附苔软体头壳
Tooltip: ""
}
PearlMolluscsHelmet: {
- DisplayName: Pearl Molluscs Helmet
+ DisplayName: çç 软体头壳
Tooltip: ""
}
ShellMolluscsBreastPlate: {
- DisplayName: Shell Molluscs Breast Plate
+ DisplayName: 软体外壳护甲
Tooltip: ""
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Critters.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Critters.hjson
index eac1ba633..9c6aa20a8 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Critters.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Critters.hjson
@@ -1,4 +1,4 @@
RiverSlugItem: {
- DisplayName: River Slug Item
+ DisplayName: 水蛞è“
Tooltip: ""
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Fishing.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Fishing.hjson
index b5783a940..7af598bd1 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Fishing.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Fishing.hjson
@@ -1,34 +1,34 @@
GlowingFirefly: {
- DisplayName: Glowing Firefly
+ DisplayName: æµè¤è¤ç«è™«
Tooltip: ""
}
DimmyFish: {
- DisplayName: Dimmy Fish
+ DisplayName: 熹光鱼
Tooltip: ""
}
Filefish: {
- DisplayName: Filefish
+ DisplayName: 马é¢é±¼
Tooltip: ""
}
GrassCarp: {
- DisplayName: Grass Carp
+ DisplayName: è‰é±¼
Tooltip: ""
}
GuidyFish: {
- DisplayName: Guidy Fish
+ DisplayName: 领路鱼
Tooltip: ""
}
ThermostatRod: {
- DisplayName: Thermostat Rod
+ DisplayName: çƒèƒ½é’“ç«¿
Tooltip: ""
}
TwilightRod: {
- DisplayName: Twilight Rod
+ DisplayName: 暮光钓竿
Tooltip: ""
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Materials.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Materials.hjson
index bb555a602..28037db91 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Materials.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Materials.hjson
@@ -1,214 +1,214 @@
StoneTusk: {
- DisplayName: Stone Tusk
+ DisplayName: 石化ç 牙
Tooltip: ""
}
BlackStarShrub: {
- DisplayName: Black Star Shrub
+ DisplayName: 黑星çŒä¸›
Tooltip: ""
}
FireflyPigment: {
- DisplayName: Firefly Pigment
+ DisplayName: æµè¤è‰²ç´
Tooltip: ""
}
GlowingPetal: {
- DisplayName: Glowing Petal
+ DisplayName: è¤ç«èŠ±ç“£
Tooltip: ""
}
MothScaleDust: {
- DisplayName: Moth Scale Dust
+ DisplayName: 飞蛾鳞片尘
Tooltip: ""
}
BlueFreeze: {
- DisplayName: Blue Freeze
+ DisplayName: ç¿ è“æœµ
Tooltip: ""
}
BluePedal: {
- DisplayName: Blue Pedal
+ DisplayName: ç‰å¤©è‹£
Tooltip: ""
}
CyanHyacinth: {
- DisplayName: Cyan Hyacinth
+ DisplayName: 天é’ç›
Tooltip: ""
}
DarkPoppy: {
- DisplayName: Dark Poppy
+ DisplayName: 暗红帽
Tooltip: ""
}
FlowerBrochure: {
- DisplayName: Flower Brochure
- Tooltip: ""
+ DisplayName: 野花收集指å—
+ Tooltip: "æºå¸¦åŽå¯ä»¥æ”¶é›†é‡Žèб"
}
GoldCup: {
- DisplayName: Gold Cup
+ DisplayName: 风摆铃
Tooltip: ""
}
GoldWhip: {
- DisplayName: Gold Whip
+ DisplayName: 金éžå…°
Tooltip: ""
}
HotPinkTulip: {
- DisplayName: Hot Pink Tulip
+ DisplayName: 粉酒æ¯èб
Tooltip: ""
}
Lavender: {
- DisplayName: Lavender
+ DisplayName: 紫笔头
Tooltip: ""
}
LightChrysanthemum: {
- DisplayName: Light Chrysanthemum
+ DisplayName: 金轮èŠ
Tooltip: ""
}
LightPurpleBalls: {
- DisplayName: Light Purple Balls
+ DisplayName: 暮色绒
Tooltip: ""
}
OrangeSausage: {
- DisplayName: Orange Sausage
+ DisplayName: ç‹ç»’è‰
Tooltip: ""
}
OrangeTulip: {
- DisplayName: Orange Tulip
+ DisplayName: 橙酒æ¯èб
Tooltip: ""
}
PinkSun: {
- DisplayName: Pink Sun
+ DisplayName: 酱粉蓟
Tooltip: ""
}
PurplePhantom: {
- DisplayName: Purple Phantom
+ DisplayName: å¹»è¶å…°
Tooltip: ""
}
PurpleTail: {
- DisplayName: Purple Tail
+ DisplayName: 紫风è‰
Tooltip: ""
}
RedFlame: {
- DisplayName: Red Flame
+ DisplayName: 赤锦
Tooltip: ""
}
ShallowNight: {
- DisplayName: Shallow Night
+ DisplayName: ç¼éœ„花
Tooltip: ""
}
SilverClock: {
- DisplayName: Silver Clock
+ DisplayName: ä¹ç“£é“¶
Tooltip: ""
}
WhiteStar: {
- DisplayName: White Star
+ DisplayName: 白锦星
Tooltip: ""
}
WhiteTulip: {
- DisplayName: White Tulip
+ DisplayName: 白酒æ¯èб
Tooltip: ""
}
WindMoveSeed: {
- DisplayName: Wind Move Seed
+ DisplayName: 风动之ç§
Tooltip: ""
}
AuburnRodSkeleton: {
- DisplayName: Auburn Rod Skeleton
+ DisplayName: 金棕飞æ£éª¨
Tooltip: ""
}
BrokenMiningLamp: {
- DisplayName: Broken Mining Lamp
+ DisplayName: æŸå矿ç¯
Tooltip: ""
}
CaterpillarJuice: {
- DisplayName: Caterpillar Juice
+ DisplayName: 虫æ±
Tooltip: ""
}
CelticKeyStone: {
- DisplayName: Celtic Key Stone
- Tooltip: ""
+ DisplayName: 凯尔特机关石
+ Tooltip: "æ”¾å…¥æš®å…‰æ£®æž—çš„ç»¿è‰²åŸŽå ¡åº•éƒ¨ä»¥æ‰“å¼€å¯†å®¤"
}
CrystalNucleusOfJellyKing: {
- DisplayName: Crystal Nucleus Of Jelly King
+ DisplayName: çƒå†»çŽ‹æ™¶æ ¸
Tooltip: ""
}
CyanVineBar: {
- DisplayName: Cyan Vine Bar
+ DisplayName: é’é”»é”
Tooltip: ""
}
LampFruit: {
- DisplayName: Lamp Fruit
+ DisplayName: ç¯æžœ
Tooltip: ""
}
LightBulbOvule: {
- DisplayName: Light Bulb Ovule
+ DisplayName: ç¯å…‰èƒšç
Tooltip: ""
}
MagicosCrystal: {
- DisplayName: Magicos Crystal
+ DisplayName: çº¯èƒ½é”æ™¶
Tooltip: ""
}
NylonRope: {
- DisplayName: Nylon Rope
+ DisplayName: 尼龙绳
Tooltip: ""
}
RodWing: {
- DisplayName: Rod Wing
+ DisplayName: 飞æ£é³
Tooltip: ""
}
TwilightCrystal: {
- DisplayName: Twilight Crystal
+ DisplayName: 暮光水晶
Tooltip: ""
}
TwilightCrystalExteactedLiquid: {
- DisplayName: Twilight Crystal Exteacted Liquid
+ DisplayName: 暮晶èƒå–æ¶²
Tooltip: ""
}
UnstablePollen: {
- DisplayName: Unstable Pollen
+ DisplayName: 脱稳花粉
Tooltip: ""
}
YggdrasilAmber: {
- DisplayName: Yggdrasil Amber
+ DisplayName: 天穹ç¥ç€
Tooltip: ""
}
DevilHeartIronBar_Item: {
- DisplayName: Devil Heart Iron Bar_ Item
+ DisplayName: é”心é“é”
Tooltip: ""
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Miscs.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Miscs.hjson
index 480b7e9b2..e212ef5aa 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Miscs.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Miscs.hjson
@@ -1,24 +1,24 @@
StarSeed: {
- DisplayName: Star Seed
+ DisplayName: 星ç§
Tooltip: ""
}
GoodNeighborCoin: {
- DisplayName: Good Neighbor Coin
+ DisplayName: 好邻居å¸
Tooltip: ""
}
JellyBallFat: {
- DisplayName: Jelly Ball Fat
+ DisplayName: çƒå†»è„‚
Tooltip: ""
}
StrongCorticalMembrane: {
- DisplayName: Strong Cortical Membrane
+ DisplayName: 强韧的皮质膜
Tooltip: ""
}
YggdrasilPlayerRoomDoorKey: {
- DisplayName: Yggdrasil Player Room Door Key
+ DisplayName: å¤©ç©¹é•‡åˆ†é…æˆ¿ä¹‹é’¥
Tooltip: ""
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Mounts.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Mounts.hjson
index 209261cb4..7295cf81d 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Mounts.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Mounts.hjson
@@ -1,4 +1,4 @@
JellyBubbleItem: {
- DisplayName: Jelly Bubble Item
+ DisplayName: çƒå†»éž
Tooltip: ""
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.PermanentBoosters.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.PermanentBoosters.hjson
index 915ad743a..83116d2af 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.PermanentBoosters.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.PermanentBoosters.hjson
@@ -1,24 +1,24 @@
PineNut: {
- DisplayName: Pine Nut
+ DisplayName: 巨形æ¾å
Tooltip: ""
}
AntiHeavenSicknessPill: {
- DisplayName: Anti Heaven Sickness Pill
+ DisplayName: 抗天穹å应è¯ä¸¸
Tooltip: ""
}
LampBorerHoney: {
- DisplayName: Lamp Borer Honey
+ DisplayName: 甘金蜜
Tooltip: ""
}
SquamousCore: {
- DisplayName: Squamous Core
+ DisplayName: 龙鳞å¤å£³æ ¸å¿ƒ
Tooltip: ""
}
JadeFruit: {
- DisplayName: Jade Fruit
+ DisplayName: 绿ç‰ç’ƒæžœ
Tooltip: ""
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Pets.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Pets.hjson
index 1e3da22f7..99ab47194 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Pets.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Pets.hjson
@@ -1,9 +1,9 @@
Badr: {
- DisplayName: Badr
+ DisplayName: “巴德尔â€
Tooltip: ""
}
LampWoodSeed: {
- DisplayName: Lamp Wood Seed
+ DisplayName: ç¯æœ¨ç§å
Tooltip: ""
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Placeables.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Placeables.hjson
index e4c5756ed..cfd61875b 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Placeables.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Placeables.hjson
@@ -1,1394 +1,1430 @@
BottleOfNutShellFlowers: {
- DisplayName: Bottle Of Nut Shell Flowers
+ DisplayName: ç“¶ä¸å¹²èб
Tooltip: ""
}
BronzeLamp_3_Item: {
- DisplayName: Bronze Lamp_3_ Item
+ DisplayName: é’é“œä¸‰ç¯æŸ±
Tooltip: ""
}
BronzeLamp_Item: {
- DisplayName: Bronze Lamp_ Item
+ DisplayName: é’é“œç¯æŸ±
Tooltip: ""
}
ChinesePartitionLamp: {
- DisplayName: Chinese Partition Lamp
+ DisplayName: ä¸å¼å±é£Žç¯
Tooltip: ""
}
ChineseStyleFloorLamp: {
- DisplayName: Chinese Style Floor Lamp
+ DisplayName: ä¸å¼åœ°ç¯
Tooltip: ""
}
DoubleArmsChineseStreetLamp: {
- DisplayName: Double Arms Chinese Street Lamp
+ DisplayName: åŒåž‚ä¸å¼è¡—ç¯ç¬¼
Tooltip: ""
}
FluoriteHangLamp: {
- DisplayName: Fluorite Hang Lamp
+ DisplayName: è§å…‰åŠç¯
Tooltip: ""
}
FluoriteLampPost_Item: {
- DisplayName: Fluorite Lamp Post_ Item
+ DisplayName: è§å…‰ç¯æŸ±
Tooltip: ""
}
GiantBell: {
- DisplayName: Giant Bell
+ DisplayName: 巨钟
Tooltip: ""
}
GiantCampFire: {
- DisplayName: Giant Camp Fire
+ DisplayName: 巨型ç¯ç«
Tooltip: ""
}
HangingSkyLantern: {
- DisplayName: Hanging Sky Lantern
+ DisplayName: 挂å¼ç¯ç¬¼
Tooltip: ""
}
HexagonalCeilingLamp: {
- DisplayName: Hexagonal Ceiling Lamp
+ DisplayName: å…角宫ç¯
Tooltip: ""
}
LapisLazuliDome_Item: {
- DisplayName: Lapis Lazuli Dome_ Item
+ DisplayName: è“色穹顶
Tooltip: ""
}
LapisLazuliDome_mini_Item: {
- DisplayName: Lapis Lazuli Dome_mini_ Item
+ DisplayName: å°åž‹è“色穹顶
Tooltip: ""
}
PierWithSlabs: {
- DisplayName: Pier With Slabs
+ DisplayName: 石æ¿çŸ³å¢©
Tooltip: ""
}
PierWithSlabsTop: {
- DisplayName: Pier With Slabs Top
+ DisplayName: 石æ¿çŸ³å¢©é¡¶
Tooltip: ""
}
PlumBlossomInABowl: {
- DisplayName: Plum Blossom InABowl
+ DisplayName: 一碗梅花
Tooltip: ""
}
SideHangingLantern_Red: {
- DisplayName: Side Hanging Lantern_ Red
+ DisplayName: 侧挂红ç¯ç¬¼
Tooltip: ""
}
SideHangingLantern_White: {
- DisplayName: Side Hanging Lantern_ White
+ DisplayName: 侧挂白ç¯ç¬¼
Tooltip: ""
}
StreetLantern: {
- DisplayName: Street Lantern
+ DisplayName: 曲æ†ä¸å¼è¡—ç¯ç¬¼
Tooltip: ""
}
WhiteCallaLily_Item: {
- DisplayName: White Calla Lily_ Item
+ DisplayName: 白色马蹄莲
Tooltip: ""
}
WhiteLotusBonsai: {
- DisplayName: White Lotus Bonsai
+ DisplayName: 白莲花盆景
Tooltip: ""
}
YellowDynastyShingles: {
- DisplayName: Yellow Dynasty Shingles
+ DisplayName: 黄王æœç“¦
Tooltip: ""
}
BlueGlassbulbBand_item: {
- DisplayName: Blue Glassbulb Band_item
- Tooltip: ""
+ DisplayName: è“LEDç¯å¸¦
+ Tooltip:
+ '''
+ 放置物为绳头
+ æ‰‹æŒæ¤ç‰©å³é”®ç‚¹å‡»ç»³å¤´å¼•出绳å
+ 把绳å牵引到å¦ä¸€å¤„绳头å†å³é”®ç‚¹å‡»å³å¯å®ŒæˆæŒ‚绳
+ 手æŒå…¶ä»–物å“,å³é”®ç‚¹å‡»æŒ‚å¥½äº†çš„ç»³å¤´å–æ¶ˆåŽŸç»³
+ æ¯ä¸ªç»³å¤´å¯ä»¥å¼•å‡ºæ— æ•°æ¡ç»³ï¼Œä½†æ˜¯åªèƒ½æŽ¥å—1æ¡ç»³
+ 控制ç¯å…‰çš„电路需è¦é€šè¿‡å¼•出绳å的绳头,接å—绳åçš„ç»³å¤´æ— æ•ˆ
+ '''
}
ChainCable_item: {
- DisplayName: Chain Cable_item
+ DisplayName: 链绳
Tooltip: ""
}
GreenGlassbulbBand_item: {
- DisplayName: Green Glassbulb Band_item
- Tooltip: ""
+ DisplayName: 绿LEDç¯å¸¦
+ Tooltip:
+ '''
+ 放置物为绳头
+ æ‰‹æŒæ¤ç‰©å³é”®ç‚¹å‡»ç»³å¤´å¼•出绳å
+ 把绳å牵引到å¦ä¸€å¤„绳头å†å³é”®ç‚¹å‡»å³å¯å®ŒæˆæŒ‚绳
+ 手æŒå…¶ä»–物å“,å³é”®ç‚¹å‡»æŒ‚å¥½äº†çš„ç»³å¤´å–æ¶ˆåŽŸç»³
+ æ¯ä¸ªç»³å¤´å¯ä»¥å¼•å‡ºæ— æ•°æ¡ç»³ï¼Œä½†æ˜¯åªèƒ½æŽ¥å—1æ¡ç»³
+ 控制ç¯å…‰çš„电路需è¦é€šè¿‡å¼•出绳å的绳头,接å—绳åçš„ç»³å¤´æ— æ•ˆ
+ '''
}
LightbulbBand_item: {
- DisplayName: Lightbulb Band_item
- Tooltip: ""
+ DisplayName: ç¯æ³¡ç¯å¸¦
+ Tooltip:
+ '''
+ 放置物为绳头
+ æ‰‹æŒæ¤ç‰©å³é”®ç‚¹å‡»ç»³å¤´å¼•出绳å
+ 把绳å牵引到å¦ä¸€å¤„绳头å†å³é”®ç‚¹å‡»å³å¯å®ŒæˆæŒ‚绳
+ 手æŒå…¶ä»–物å“,å³é”®ç‚¹å‡»æŒ‚å¥½äº†çš„ç»³å¤´å–æ¶ˆåŽŸç»³
+ æ¯ä¸ªç»³å¤´å¯ä»¥å¼•å‡ºæ— æ•°æ¡ç»³ï¼Œä½†æ˜¯åªèƒ½æŽ¥å—1æ¡ç»³
+ 控制ç¯å…‰çš„电路需è¦é€šè¿‡å¼•出绳å的绳头,接å—绳åçš„ç»³å¤´æ— æ•ˆ
+ '''
}
RedGlassbulbBand_item: {
- DisplayName: Red Glassbulb Band_item
- Tooltip: ""
+ DisplayName: 红LEDç¯å¸¦
+ Tooltip:
+ '''
+ 放置物为绳头
+ æ‰‹æŒæ¤ç‰©å³é”®ç‚¹å‡»ç»³å¤´å¼•出绳å
+ 把绳å牵引到å¦ä¸€å¤„绳头å†å³é”®ç‚¹å‡»å³å¯å®ŒæˆæŒ‚绳
+ 手æŒå…¶ä»–物å“,å³é”®ç‚¹å‡»æŒ‚å¥½äº†çš„ç»³å¤´å–æ¶ˆåŽŸç»³
+ æ¯ä¸ªç»³å¤´å¯ä»¥å¼•å‡ºæ— æ•°æ¡ç»³ï¼Œä½†æ˜¯åªèƒ½æŽ¥å—1æ¡ç»³
+ 控制ç¯å…‰çš„电路需è¦é€šè¿‡å¼•出绳å的绳头,接å—绳åçš„ç»³å¤´æ— æ•ˆ
+ '''
}
ChoppingBlock_Item: {
- DisplayName: Chopping Block_ Item
+ DisplayName: åŽ¨ç”¨ç §æ¿
Tooltip: ""
}
CleaverRack_Item: {
- DisplayName: Cleaver Rack_ Item
+ DisplayName: 刀具挂排
Tooltip: ""
}
CookwareRack_Item: {
- DisplayName: Cookware Rack_ Item
+ DisplayName: 锅铲挂排
Tooltip: ""
}
Hob_Silver_Item: {
- DisplayName: Hob_ Silver_ Item
+ DisplayName: 银色厨柜
Tooltip: ""
}
Refrigerator_Silver_Item: {
- DisplayName: Refrigerator_ Silver_ Item
+ DisplayName: 银色冰箱
Tooltip: ""
}
Stove_Item: {
- DisplayName: Stove_ Item
+ DisplayName: 炉ç¶
Tooltip: ""
}
AirTileItem: {
- DisplayName: Air Tile Item
- Tooltip: ""
+ DisplayName: 空å—
+ Tooltip: "å¼€å‘者物å“"
}
AirWallItem: {
- DisplayName: Air Wall Item
- Tooltip: ""
+ DisplayName: 空墙
+ Tooltip: "å¼€å‘者物å“"
}
CableCarJoin_item: {
- DisplayName: Cable Car Join_item
+ DisplayName: 缆车节点
Tooltip: ""
}
CreatPineTree: {
- DisplayName: Creat Pine Tree
- Tooltip: ""
+ DisplayName: å»ºé€ å·¨å¤§é›ªæ¾
+ Tooltip: "å¼€å‘者物å“"
}
SnowPineChest: {
- DisplayName: Snow Pine Chest
+ DisplayName: 雪æ¾å®ç®±
Tooltip: ""
}
SnowPineChest_fresh: {
- DisplayName: Snow Pine Chest_fresh
+ DisplayName: 雪æ¾å®ç®±
Tooltip: ""
}
SnowPineChest_gold: {
- DisplayName: Snow Pine Chest_gold
+ DisplayName: 雪æ¾å®ç®±
Tooltip: ""
}
SnowPineDoor: {
- DisplayName: Snow Pine Door
+ DisplayName: 雪æ¾é—¨
Tooltip: ""
}
SnowPineLeaveStaff: {
- DisplayName: Snow Pine Leave Staff
+ DisplayName: 雪æ¾é’ˆå¶æ³•æ–
Tooltip: ""
}
SnowPineLeavesWall: {
- DisplayName: Snow Pine Leaves Wall
+ DisplayName: 雪æ¾é’ˆå¶å¢™
Tooltip: ""
}
SnowPineWoodStaff: {
- DisplayName: Snow Pine Wood Staff
+ DisplayName: 雪æ¾åŽŸæœ¨æ³•æ–
Tooltip: ""
}
SnowPineWoodWall: {
- DisplayName: Snow Pine Wood Wall
+ DisplayName: é›ªæ¾æœ¨å¢™
Tooltip: ""
}
SungloChandelier: {
- DisplayName: Sunglo Chandelier
+ DisplayName: æ¾èåŠç¯
Tooltip: ""
}
Thatched: {
- DisplayName: Thatched
+ DisplayName: 屋用茅è‰
Tooltip: ""
}
ThatchedWall: {
- DisplayName: Thatched Wall
+ DisplayName: 屋用茅è‰å¢™
Tooltip: ""
}
PineLiftWinch: {
- DisplayName: Pine Lift Winch
+ DisplayName: æ¾æ ‘电梯
Tooltip: ""
}
BloodMossStone: {
- DisplayName: Blood Moss Stone
+ DisplayName: 血苔石
Tooltip: ""
}
BloodyStoneWall: {
- DisplayName: Bloody Stone Wall
+ DisplayName: 血苔石墙
Tooltip: ""
}
TuskFlesh_Item: {
- DisplayName: Tusk Flesh_ Item
+ DisplayName: ç 牙龈å—
Tooltip: ""
}
TuskStatusI: {
- DisplayName: Tusk Status I
+ DisplayName: ç 牙石碑
Tooltip: ""
}
TuskStatusII: {
- DisplayName: Tusk StatusII
+ DisplayName: ç 牙石碑
Tooltip: ""
}
TuskStatusIII: {
- DisplayName: Tusk StatusIII
+ DisplayName: ç 牙石碑
Tooltip: ""
}
TuskStatusIV: {
- DisplayName: Tusk StatusIV
+ DisplayName: ç 牙石碑
Tooltip: ""
}
BloodyTuskTrophy: {
- DisplayName: Bloody Tusk Trophy
+ DisplayName: 鲜血ç 牙纪念ç«
Tooltip: ""
}
TuskRelic: {
- DisplayName: Tusk Relic
+ DisplayName: 鲜血ç 牙圣物
Tooltip: ""
}
FireflyPylonItem: {
- DisplayName: Firefly Pylon Item
+ DisplayName: æµè¤æ™¶å¡”
Tooltip: ""
}
ShabbyPylonItem: {
- DisplayName: Shabby Pylon Item
+ DisplayName: ç ´æ—§æ™¶å¡”
Tooltip: ""
}
BlackVine: {
- DisplayName: Black Vine
+ DisplayName: 黑藤
Tooltip: ""
}
CorruptOrbStonePost: {
- DisplayName: Corrupt Orb Stone Post
+ DisplayName: è…化法术石柱
Tooltip: ""
}
CrimsonOrbStonePost: {
- DisplayName: Crimson Orb Stone Post
+ DisplayName: 猩红法术石柱
Tooltip: ""
}
DarkCocoon: {
- DisplayName: Dark Cocoon
+ DisplayName: 暗茧
Tooltip: ""
}
DarkCocoonWall: {
- DisplayName: Dark Cocoon Wall
+ DisplayName: 暗茧墙
Tooltip: ""
}
DarkCocoonWithPetal: {
- DisplayName: Dark Cocoon With Petal
+ DisplayName: 花瓣暗茧墙
Tooltip: ""
}
FireflyPiranhaBanner: {
- DisplayName: Firefly Piranha Banner
+ DisplayName: æµè¤è™Žé±¼æ——
Tooltip: ""
}
GlowingReedSeed: {
- DisplayName: Glowing Reed Seed
+ DisplayName: 夜光芦苇ç§å
Tooltip: ""
}
GlowWood: {
- DisplayName: Glow Wood
+ DisplayName: è¤ç«æœ¨
Tooltip: ""
}
GlowWoodWall: {
- DisplayName: Glow Wood Wall
+ DisplayName: è¤ç«æœ¨å¢™
Tooltip: ""
}
LiveFluorescentLeafWall: {
- DisplayName: Live Fluorescent Leaf Wall
+ DisplayName: 生命è¤ç«å¶å¢™
Tooltip: ""
}
LiveFluorescentWoodWall: {
- DisplayName: Live Fluorescent Wood Wall
+ DisplayName: 生命è¤ç«æœ¨å¢™
Tooltip: ""
}
FluorescentLeafStaff: {
- DisplayName: Fluorescent Leaf Staff
+ DisplayName: 生命è¤ç«å¶æ³•æ–
Tooltip: ""
}
FluorescentWoodStaff: {
- DisplayName: Fluorescent Wood Staff
+ DisplayName: 生命è¤ç«æœ¨æ³•æ–
Tooltip: ""
}
GlowingDrop: {
- DisplayName: Glowing Drop
+ DisplayName: è¤ç«åŠ
Tooltip: ""
}
GlowWoodBathtub: {
- DisplayName: Glow Wood Bathtub
+ DisplayName: è¤ç«æœ¨æµ´ç¼¸
Tooltip: ""
}
GlowWoodBed: {
- DisplayName: Glow Wood Bed
+ DisplayName: è¤ç«æœ¨åºŠ
Tooltip: ""
}
GlowWoodBookcase: {
- DisplayName: Glow Wood Bookcase
+ DisplayName: è¤ç«æœ¨ä¹¦æž¶
Tooltip: ""
}
GlowWoodCampfire: {
- DisplayName: Glow Wood Campfire
+ DisplayName: è¤ç«æœ¨ç¯ç«
Tooltip: ""
}
GlowWoodCandelabra: {
- DisplayName: Glow Wood Candelabra
+ DisplayName: è¤ç«æœ¨çƒ›å°
Tooltip: ""
}
GlowWoodCandle: {
- DisplayName: Glow Wood Candle
+ DisplayName: è¤ç«æœ¨èœ¡çƒ›
Tooltip: ""
}
GlowWoodChair: {
- DisplayName: Glow Wood Chair
+ DisplayName: è¤ç«æœ¨æ¤…
Tooltip: ""
}
GlowWoodChandelier: {
- DisplayName: Glow Wood Chandelier
+ DisplayName: è¤ç«æœ¨åŠç¯
Tooltip: ""
}
GlowWoodChandelierType2: {
- DisplayName: Glow Wood Chandelier Type2
+ DisplayName: è¤ç«æœ¨åŠç¯
Tooltip: ""
}
GlowWoodChandelierType3: {
- DisplayName: Glow Wood Chandelier Type3
+ DisplayName: è¤ç«æœ¨åŠç¯
Tooltip: ""
}
GlowWoodChandelierType4: {
- DisplayName: Glow Wood Chandelier Type4
+ DisplayName: è¤ç«æœ¨åŠç¯
Tooltip: ""
}
GlowWoodChest: {
- DisplayName: Glow Wood Chest
+ DisplayName: è¤ç«æœ¨ç®±
Tooltip: ""
}
GlowWoodClock: {
- DisplayName: Glow Wood Clock
+ DisplayName: è¤ç«æœ¨é’Ÿ
Tooltip: ""
}
GlowWoodDoor: {
- DisplayName: Glow Wood Door
+ DisplayName: è¤ç«æœ¨é—¨
Tooltip: ""
}
GlowWoodDoorType2: {
- DisplayName: Glow Wood Door Type2
+ DisplayName: è¤ç«æœ¨é—¨
Tooltip: ""
}
GlowWoodDresser: {
- DisplayName: Glow Wood Dresser
+ DisplayName: è¤ç«æœ¨æ¢³å¦†å°
Tooltip: ""
}
GlowWoodDresserType2: {
- DisplayName: Glow Wood Dresser Type2
+ DisplayName: è¤ç«æœ¨æ¢³å¦†å°
Tooltip: ""
}
GlowWoodLamp: {
- DisplayName: Glow Wood Lamp
+ DisplayName: è¤ç«æœ¨ç¯
Tooltip: ""
}
GlowWoodLantern: {
- DisplayName: Glow Wood Lantern
+ DisplayName: è¤ç«æœ¨ç¯ç¬¼
Tooltip: ""
}
GlowWoodLanternType2: {
- DisplayName: Glow Wood Lantern Type2
+ DisplayName: è¤ç«æœ¨ç¯ç¬¼
Tooltip: ""
}
GlowWoodMusicBox: {
- DisplayName: Glow Wood Music Box
+ DisplayName: 八音盒(æµè¤ä¹‹åœ°ï¼‰
Tooltip: ""
}
GlowWoodPiano: {
- DisplayName: Glow Wood Piano
+ DisplayName: è¤ç«æœ¨é’¢ç´
Tooltip: ""
}
GlowWoodPlatform: {
- DisplayName: Glow Wood Platform
+ DisplayName: è¤ç«æœ¨å¹³å°
Tooltip: ""
}
GlowWoodSink: {
- DisplayName: Glow Wood Sink
+ DisplayName: è¤ç«æœ¨æ°´æ§½
Tooltip: ""
}
GlowWoodSinkType2: {
- DisplayName: Glow Wood Sink Type2
+ DisplayName: è¤ç«æœ¨æ°´æ§½
Tooltip: ""
}
GlowWoodSofa: {
- DisplayName: Glow Wood Sofa
+ DisplayName: è¤ç«æœ¨æ²™å‘
Tooltip: ""
}
GlowWoodTable: {
- DisplayName: Glow Wood Table
+ DisplayName: è¤ç«æœ¨æ¡Œ
Tooltip: ""
}
GlowWoodToilet: {
- DisplayName: Glow Wood Toilet
+ DisplayName: è¤ç«æœ¨é©¬æ¡¶
Tooltip: ""
}
GlowWoodTorch: {
- DisplayName: Glow Wood Torch
+ DisplayName: è¤ç«æœ¨ç«æŠŠ
Tooltip: ""
}
GlowWoodWorkBench: {
- DisplayName: Glow Wood Work Bench
+ DisplayName: è¤ç«æœ¨å·¥ä½œå°
Tooltip: ""
}
MothRelic: {
- DisplayName: Moth Relic
+ DisplayName: è…æª€å·¨è›¾åœ£ç‰©
Tooltip: ""
}
FireCrackerLauncher: {
- DisplayName: Fire Cracker Launcher
+ DisplayName: 礼花弹å‘射管
Tooltip: ""
}
RoomBlackBox_Item: {
- DisplayName: Room Black Box_ Item
- Tooltip: ""
+ DisplayName: 房间世界的黑匣å
+ Tooltip: "å¼€å‘者物å“"
}
WoodenRoomDoor_exit_Item: {
- DisplayName: Wooden Room Door_exit_ Item
- Tooltip: ""
+ DisplayName: 离开房间的木门
+ Tooltip: "å³é”®ç¦»å¼€æˆ¿é—´"
}
WoodenRoomDoor_Item: {
- DisplayName: Wooden Room Door_ Item
- Tooltip: ""
+ DisplayName: 进入房间的木门
+ Tooltip: "å³é”®è¿›å…¥ä¸€ä¸ªæœ¨åˆ¶çš„æˆ¿é—´"
}
ChineseKitchenDoor_Item: {
- DisplayName: Chinese Kitchen Door_ Item
- Tooltip: ""
+ DisplayName: ä¸å¼åŽ¨æˆ¿é—¨
+ Tooltip:
+ '''
+ å³é”®é—¨å¯ä»¥è¿›å…¥ä¸€ä¸ªä¸å¼é£Žæ ¼çš„åŽ¨æˆ¿ï¼Œæ ¹æ®æç¤ºå¯ä»¥å¼€å¯é¤åŽ…ç»è¥æ¸¸æˆ
+ é¤åŽ…ç»è¥æ¸¸æˆå¯ä»¥è§£é”æ–°çš„èœè°±
+ '''
}
RestaurantLogoBoard_Item: {
- DisplayName: Restaurant Logo Board_ Item
+ DisplayName: é¤åŽ…æ ‡å¿—
Tooltip: ""
}
ServingCounter_ChineseStyle_Item: {
- DisplayName: Serving Counter_ Chinese Style_ Item
- Tooltip: ""
+ DisplayName: ä¸å¼æœåŠ¡å°
+ Tooltip: "把符åˆè®¢å•çš„èœå“放上去或从上空丢过去以完æˆè®¢å•"
}
ExitUnionTile_Item: {
- DisplayName: Exit Union Tile_ Item
+ DisplayName: 离开工会的门
Tooltip: ""
}
GiantFurnacePlaceItem: {
- DisplayName: Giant Furnace Place Item
- Tooltip: ""
+ DisplayName: 巨型炉心
+ Tooltip: "真的超大一个"
}
CanteenDoor_Item: {
- DisplayName: Canteen Door_ Item
+ DisplayName: 进入é¤åŽ…é—¨
Tooltip: ""
}
CanteenExit_Item: {
- DisplayName: Canteen Exit_ Item
+ DisplayName: 离开é¤åŽ…é—¨
Tooltip: ""
}
CurrentEnergyTube_Item: {
- DisplayName: Current Energy Tube_ Item
+ DisplayName: 能æµç®¡
Tooltip: ""
}
DarkForestSoil_Item: {
- DisplayName: Dark Forest Soil_ Item
+ DisplayName: 暗森土壤
Tooltip: ""
}
DarkSludge_Item: {
- DisplayName: Dark Sludge_ Item
+ DisplayName: 黑沼泥
Tooltip: ""
}
DilapidatedDangerSigns: {
- DisplayName: Dilapidated Danger Signs
+ DisplayName: “å°å¿ƒåœ°æ»‘â€
Tooltip: ""
}
ExitSignBoard_Item: {
- DisplayName: Exit Sign Board_ Item
+ DisplayName: 安全出å£
Tooltip: ""
}
FemaleLampLeaves_Item: {
- DisplayName: Female Lamp Leaves_ Item
+ DisplayName: ç¯æœ¨æ¯æ ‘原木
Tooltip: ""
}
FloorScaleForPlayers_Item: {
- DisplayName: Floor Scale For Players_ Item
- Tooltip: ""
+ DisplayName: 炉心区地磅
+ Tooltip: "站上去åŽç‚‰å¿ƒåŒºçš„贡献程åºä¼šèŽ·å¾—çŽ©å®¶èº«ä»½"
}
FurnaceCopperGear_Large_Item: {
- DisplayName: Furnace Copper Gear_ Large_ Item
+ DisplayName: 大型炉心铜齿轮
Tooltip: ""
}
FurnaceCopperGear_Middle_Item: {
- DisplayName: Furnace Copper Gear_ Middle_ Item
+ DisplayName: ä¸åž‹ç‚‰å¿ƒé“œé½¿è½®
Tooltip: ""
}
FurnaceCopperPipe_Item: {
- DisplayName: Furnace Copper Pipe_ Item
+ DisplayName: 炉心铜管
Tooltip: ""
}
FurnaceCopperPipe_Large_Corner_Item: {
- DisplayName: Furnace Copper Pipe_ Large_ Corner_ Item
+ DisplayName: 炉心大铜管转角
Tooltip: ""
}
FurnaceCopperPipe_Large_Item: {
- DisplayName: Furnace Copper Pipe_ Large_ Item
+ DisplayName: 炉心大铜管
Tooltip: ""
}
FurnaceEmergencyLamp_Item: {
- DisplayName: Furnace Emergency Lamp_ Item
+ DisplayName: 炉心应急ç¯
Tooltip: ""
}
FurnaceHeatProofPlatingWall_Item: {
- DisplayName: Furnace Heat Proof Plating Wall_ Item
+ DisplayName: 炉心强效隔çƒé•€å±‚墙
Tooltip: ""
}
FurnaceLavaband_Item: {
- DisplayName: Furnace Lavaband_ Item
+ DisplayName: 炉心熔岩ç¯å¸¦
Tooltip: ""
}
FurnaceLavaLamp_Item: {
- DisplayName: Furnace Lava Lamp_ Item
+ DisplayName: 炉心熔岩ç¯
Tooltip: ""
}
FurnacePlatingBlock: {
- DisplayName: Furnace Plating Block
+ DisplayName: 炉心镀层å—
Tooltip: ""
}
FurnaceTrapDoor_Item: {
- DisplayName: Furnace Trap Door_ Item
+ DisplayName: 炉心活æ¿é—¨
Tooltip: ""
}
GreenRelicBrick_Item: {
- DisplayName: Green Relic Brick_ Item
+ DisplayName: 绿é—è¿¹ç –
Tooltip: ""
}
GreyTownBrick_Item: {
- DisplayName: Grey Town Brick_ Item
+ DisplayName: 城镇ç°çŸ³ç –
Tooltip: ""
}
HeatProofPlatingWall_Item: {
- DisplayName: Heat Proof Plating Wall_ Item
+ DisplayName: 炉心隔çƒé•€å±‚墙
Tooltip: ""
}
IronTrackScaffolding: {
- DisplayName: Iron Track Scaffolding
+ DisplayName: 铿”¯æž¶
Tooltip: ""
}
Ishta_per_The_Venus_painting_Item: {
- DisplayName: Ishta_per_ The_ Venus_painting_ Item
+ DisplayName: 伊斯塔裴尔的画åƒ
Tooltip: ""
}
JellyBallCube: {
- DisplayName: Jelly Ball Cube
+ DisplayName: çƒå†»æ–¹å—
Tooltip: ""
}
Lamorch_Item: {
- DisplayName: Lamorch_ Item
+ DisplayName: ç¯æŠŠ
Tooltip: ""
}
LampGrassSeed: {
- DisplayName: Lamp Grass Seed
+ DisplayName: ç¯æœ¨æž—ç´«è‰ç±½
Tooltip: ""
}
LampWoodCrate_Item: {
- DisplayName: Lamp Wood Crate_ Item
+ DisplayName: ç¯æœ¨åŒ£
Tooltip: ""
}
LampWood_Wood: {
- DisplayName: Lamp Wood_ Wood
+ DisplayName: ç¯æœ¨
Tooltip: ""
}
LargeCrystalShowTable_Blue_Item: {
- DisplayName: Large Crystal Show Table_ Blue_ Item
+ DisplayName: 大型暮晶æ“作å°
Tooltip: ""
}
LargeCrystalShowTable_Green_Item: {
- DisplayName: Large Crystal Show Table_ Green_ Item
+ DisplayName: è“æ™¶ä½“展å°
Tooltip: ""
}
LargeCrystalShowTable_Red_Item: {
- DisplayName: Large Crystal Show Table_ Red_ Item
+ DisplayName: 红晶体展å°
Tooltip: ""
}
MeltingButton_Item: {
- DisplayName: Melting Button_ Item
- Tooltip: ""
+ DisplayName: 熔炼按钮
+ Tooltip: "æŒ‰ä¸‹åŽæŠŠç†”æ–™æ”¶çº³ç®±çš„ç‰©ä½“é”€æ¯ï¼Œè½¬åŒ–为çƒèƒ½å¹¶è®°å½•贡献点"
}
MeltingInputBox_Item: {
- DisplayName: Melting Input Box_ Item
+ DisplayName: 熔料收纳箱
Tooltip: ""
}
MissionBoard_Item: {
- DisplayName: Mission Board_ Item
+ DisplayName: ä»»åŠ¡æ‚¬èµæ¿
Tooltip: ""
}
MissionCounter_Item: {
- DisplayName: Mission Counter_ Item
+ DisplayName: 任务柜å°
Tooltip: ""
}
RoadSignPost_ToArena_Item: {
- DisplayName: Road Sign Post_ To Arena_ Item
+ DisplayName: é€šå¾€ç«žæŠ€åœºçš„è·¯æ ‡
Tooltip: ""
}
RuinTorch: {
- DisplayName: Ruin Torch
+ DisplayName: é—è¿¹ç«æŠŠ
Tooltip: ""
}
SteamBoiler_Item: {
- DisplayName: Steam Boiler_ Item
+ DisplayName: 蒸汽锅炉
Tooltip: ""
}
StoneBridge_Chest_item: {
- DisplayName: Stone Bridge_ Chest_item
+ DisplayName: 石桥箱
Tooltip: ""
}
StoneDragonScaleWood: {
- DisplayName: Stone Dragon Scale Wood
+ DisplayName: 石化龙鳞木
Tooltip: ""
}
TotalFurnaceScoreBoard_Item: {
- DisplayName: Total Furnace Score Board_ Item
+ DisplayName: 炉心çƒå€¼è´¡çŒ®æ¿
Tooltip: ""
}
TownBrick_Gray_Item: {
- DisplayName: Town Brick_ Gray_ Item
+ DisplayName: 城镇亮ç°ç –
Tooltip: ""
}
TownBrick_Khaki_Item: {
- DisplayName: Town Brick_ Khaki_ Item
+ DisplayName: 城镇å¡å…¶ç –
Tooltip: ""
}
TownSteelBrick_Item: {
- DisplayName: Town Steel Brick_ Item
+ DisplayName: åŸŽé•‡è´´é•€å±‚ç –
Tooltip: ""
}
TwilightCrate_Item: {
- DisplayName: Twilight Crate_ Item
+ DisplayName: 暮光匣
Tooltip: ""
}
TwilightEucalyptusWood_Item: {
- DisplayName: Twilight Eucalyptus Wood_ Item
+ DisplayName: 暮光桉木
Tooltip: ""
}
UnionAcanthusWallLace_Item: {
- DisplayName: Union Acanthus Wall Lace_ Item
+ DisplayName: 工会茛苕å¶é‡‘è¾¹
Tooltip: ""
}
UnionGiantChandelier_Item: {
- DisplayName: Union Giant Chandelier_ Item
+ DisplayName: 工会巨型水晶åŠç¯
Tooltip: ""
}
UnionGiantChandelier_Style1_Item: {
- DisplayName: Union Giant Chandelier_ Style1_ Item
+ DisplayName: 工会巨型åŠç¯
Tooltip: ""
}
UnionGoldAcanthusWall_Item: {
- DisplayName: Union Gold Acanthus Wall_ Item
+ DisplayName: 工会茛苕å¶çº¹å¢™
Tooltip: ""
}
UnionLampPost_Style0_Item: {
- DisplayName: Union Lamp Post_ Style0_ Item
+ DisplayName: 工会金å°ç¯
Tooltip: ""
}
UnionLampPost_Style1_Item: {
- DisplayName: Union Lamp Post_ Style1_ Item
+ DisplayName: 工会ç‰ç’ƒå°ç¯
Tooltip: ""
}
UnionLampPost_Style2_Item: {
- DisplayName: Union Lamp Post_ Style2_ Item
+ DisplayName: 工会雕åƒå°ç¯
Tooltip: ""
}
UnionMarblePost_Body_Khaki_Item: {
- DisplayName: Union Marble Post_ Body_ Khaki_ Item
+ DisplayName: 工会å¡å…¶è‰²å¤§ç†çŸ³ç«‹æŸ±æŸ±ä½“
Tooltip: ""
}
UnionMarblePost_Bottom_Khaki_Item: {
- DisplayName: Union Marble Post_ Bottom_ Khaki_ Item
+ DisplayName: 工会å¡å…¶è‰²å¤§ç†çŸ³ç«‹æŸ±åº•座
Tooltip: ""
}
UnionMarblePost_Top_Corinth_Khaki_Item: {
- DisplayName: Union Marble Post_ Top_ Corinth_ Khaki_ Item
+ DisplayName: 工会柯林斯å¼å¡å…¶è‰²å¤§ç†çŸ³ç«‹æŸ±é¡¶
Tooltip: ""
}
UnionMarblePost_Top_Doric_Khaki_Item: {
- DisplayName: Union Marble Post_ Top_ Doric_ Khaki_ Item
+ DisplayName: 工会多立克å¼å¡å…¶è‰²å¤§ç†çŸ³ç«‹æŸ±é¡¶
Tooltip: ""
}
UnionMarblePost_Top_Ionic_Khaki_Item: {
- DisplayName: Union Marble Post_ Top_ Ionic_ Khaki_ Item
+ DisplayName: 工会罗马å¼å¡å…¶è‰²å¤§ç†çŸ³ç«‹æŸ±é¡¶
Tooltip: ""
}
UnionMarbleTile_Khaki_Item: {
- DisplayName: Union Marble Tile_ Khaki_ Item
+ DisplayName: 工会å¡å…¶è‰²å¤§ç†çŸ³å—
Tooltip: ""
}
UnionMarbleWall_Dark_Item: {
- DisplayName: Union Marble Wall_ Dark_ Item
+ DisplayName: 工会暗色大ç†çŸ³å¢™
Tooltip: ""
}
UnionOfficeDoor_Item: {
- DisplayName: Union Office Door_ Item
+ DisplayName: 工会办公室大门
Tooltip: ""
}
UnionSideLantern_Style0_Item: {
- DisplayName: Union Side Lantern_ Style0_ Item
+ DisplayName: 工会金侧ç¯
Tooltip: ""
}
UnionWallLamp_Style0_Item: {
- DisplayName: Union Wall Lamp_ Style0_ Item
+ DisplayName: 工会大ç†çŸ³å£ç¯
Tooltip: ""
}
UnionWindow_Style0_Item: {
- DisplayName: Union Window_ Style0_ Item
+ DisplayName: 工会窗
Tooltip: ""
}
Union_Y_Stairs_Item: {
- DisplayName: Union_ Y_ Stairs_ Item
+ DisplayName: 工会Y形大楼梯
Tooltip: ""
}
UrbanCrate_Item: {
- DisplayName: Urban Crate_ Item
+ DisplayName: 城镇匣
Tooltip: ""
}
YggdrasilCommandBlockItem: {
- DisplayName: Yggdrasil Command Block Item
+ DisplayName: 天穹命令方å—
Tooltip: ""
}
YggdrasilPlayerRoomDoor_Item: {
- DisplayName: Yggdrasil Player Room Door_ Item
+ DisplayName: 天穹镇ä½å®…é—¨
Tooltip: ""
}
YggdrasilPlayerRoomDoor_Lock_Item: {
- DisplayName: Yggdrasil Player Room Door_ Lock_ Item
+ DisplayName: 上é”天穹镇ä½å®…é—¨
Tooltip: ""
}
GreenRelicWall_Item: {
- DisplayName: Green Relic Wall_ Item
+ DisplayName: 绿é—è¿¹ç –å¢™
Tooltip: ""
}
JellyBallSecretionWall_Item: {
- DisplayName: Jelly Ball Secretion Wall_ Item
+ DisplayName: çƒå†»åˆ†æ³Œç‰©å¢™
Tooltip: ""
}
LampWoodWall_item: {
- DisplayName: Lamp Wood Wall_item
+ DisplayName: ç¯æœ¨å¢™
Tooltip: ""
}
StoneDragonScaleWoodWall_Item: {
- DisplayName: Stone Dragon Scale Wood Wall_ Item
+ DisplayName: 石化龙鳞木墙
Tooltip: ""
}
TownBrick_Gray_Wall_Item: {
- DisplayName: Town Brick_ Gray_ Wall_ Item
+ DisplayName: 城镇亮ç°ç –墙
Tooltip: ""
}
TownBrick_Khaki_Wall_Item: {
- DisplayName: Town Brick_ Khaki_ Wall_ Item
+ DisplayName: 城镇å¡å…¶ç –墙
Tooltip: ""
}
TwilightEucalyptusWoodWall_Item: {
- DisplayName: Twilight Eucalyptus Wood Wall_ Item
+ DisplayName: 暮光桉木墙
Tooltip: ""
}
CyanVineOre: {
- DisplayName: Cyan Vine Ore
+ DisplayName: é’缎矿
Tooltip: ""
}
RustBronzeTreasureChest_Item: {
- DisplayName: Rust Bronze Treasure Chest_ Item
+ DisplayName: 锈铜å®ç®±
Tooltip: ""
}
TwilightCrystalMill_Item: {
- DisplayName: Twilight Crystal Mill_ Item
+ DisplayName: 暮晶磨
Tooltip: ""
}
TwilightEucalyptusBathtub: {
- DisplayName: Twilight Eucalyptus Bathtub
+ DisplayName: 暮光桉浴缸
Tooltip: ""
}
TwilightEucalyptusBed: {
- DisplayName: Twilight Eucalyptus Bed
+ DisplayName: 暮光桉床
Tooltip: ""
}
TwilightEucalyptusBookcase: {
- DisplayName: Twilight Eucalyptus Bookcase
+ DisplayName: 暮光桉书架
Tooltip: ""
}
TwilightEucalyptusCandelabra: {
- DisplayName: Twilight Eucalyptus Candelabra
+ DisplayName: 暮光桉烛å°
Tooltip: ""
}
TwilightEucalyptusCandle: {
- DisplayName: Twilight Eucalyptus Candle
+ DisplayName: 暮光桉蜡烛
Tooltip: ""
}
TwilightEucalyptusChair: {
- DisplayName: Twilight Eucalyptus Chair
+ DisplayName: 暮光桉椅
Tooltip: ""
}
TwilightEucalyptusChandelier: {
- DisplayName: Twilight Eucalyptus Chandelier
+ DisplayName: 暮光桉åŠç¯
Tooltip: ""
}
TwilightEucalyptusChest: {
- DisplayName: Twilight Eucalyptus Chest
+ DisplayName: 暮光桉箱
Tooltip: ""
}
TwilightEucalyptusClock: {
- DisplayName: Twilight Eucalyptus Clock
+ DisplayName: 暮光桉钟
Tooltip: ""
}
TwilightEucalyptusDoor: {
- DisplayName: Twilight Eucalyptus Door
+ DisplayName: 暮光桉门
Tooltip: ""
}
TwilightEucalyptusDresser: {
- DisplayName: Twilight Eucalyptus Dresser
+ DisplayName: 暮光桉梳妆å°
Tooltip: ""
}
TwilightEucalyptusLamp: {
- DisplayName: Twilight Eucalyptus Lamp
+ DisplayName: 暮光桉ç¯
Tooltip: ""
}
TwilightEucalyptusLantern: {
- DisplayName: Twilight Eucalyptus Lantern
+ DisplayName: 暮光桉ç¯ç¬¼
Tooltip: ""
}
TwilightEucalyptusPiano: {
- DisplayName: Twilight Eucalyptus Piano
+ DisplayName: 暮光桉钢ç´
Tooltip: ""
}
TwilightEucalyptusPlatform: {
- DisplayName: Twilight Eucalyptus Platform
+ DisplayName: 暮光桉平å°
Tooltip: ""
}
TwilightEucalyptusSink: {
- DisplayName: Twilight Eucalyptus Sink
+ DisplayName: 暮光桉水槽
Tooltip: ""
}
TwilightEucalyptusSofa: {
- DisplayName: Twilight Eucalyptus Sofa
+ DisplayName: 暮光桉沙å‘
Tooltip: ""
}
TwilightEucalyptusSofa_Type2: {
- DisplayName: Twilight Eucalyptus Sofa_ Type2
+ DisplayName: 暮光桉沙å‘
Tooltip: ""
}
TwilightEucalyptusTable: {
- DisplayName: Twilight Eucalyptus Table
+ DisplayName: 暮光桉桌
Tooltip: ""
}
TwilightEucalyptusToilet: {
- DisplayName: Twilight Eucalyptus Toilet
+ DisplayName: 暮光桉马桶
Tooltip: ""
}
TwilightEucalyptusWorkBench: {
- DisplayName: Twilight Eucalyptus Work Bench
+ DisplayName: 暮光桉工作å°
Tooltip: ""
}
LampWoodBathtub: {
- DisplayName: Lamp Wood Bathtub
+ DisplayName: ç¯æœ¨æµ´ç¼¸
Tooltip: ""
}
LampWoodBed: {
- DisplayName: Lamp Wood Bed
+ DisplayName: ç¯æœ¨åºŠ
Tooltip: ""
}
LampWoodBookcase: {
- DisplayName: Lamp Wood Bookcase
+ DisplayName: ç¯æœ¨ä¹¦æž¶
Tooltip: ""
}
LampWoodCandelabra_Item: {
- DisplayName: Lamp Wood Candelabra_ Item
+ DisplayName: ç¯æœ¨çƒ›å°
Tooltip: ""
}
LampWoodCandle_Item: {
- DisplayName: Lamp Wood Candle_ Item
+ DisplayName: ç¯æœ¨èœ¡çƒ›
Tooltip: ""
}
LampWoodChair: {
- DisplayName: Lamp Wood Chair
+ DisplayName: ç¯æœ¨æ¤…
Tooltip: ""
}
LampWoodChandelier_Item: {
- DisplayName: Lamp Wood Chandelier_ Item
+ DisplayName: ç¯æœ¨åŠç¯
Tooltip: ""
}
LampWoodClock: {
- DisplayName: Lamp Wood Clock
+ DisplayName: ç¯æœ¨é’Ÿ
Tooltip: ""
}
LampWoodDoor: {
- DisplayName: Lamp Wood Door
+ DisplayName: ç¯æœ¨é—¨
Tooltip: ""
}
LampWoodDresser: {
- DisplayName: Lamp Wood Dresser
+ DisplayName: ç¯æœ¨æ¢³å¦†å°
Tooltip: ""
}
LampWoodLamp_Item: {
- DisplayName: Lamp Wood Lamp_ Item
+ DisplayName: ç¯æœ¨ç¯
Tooltip: ""
}
LampWoodLantern: {
- DisplayName: Lamp Wood Lantern
+ DisplayName: ç¯æœ¨ç¯ç¬¼
Tooltip: ""
}
LampWoodPiano: {
- DisplayName: Lamp Wood Piano
+ DisplayName: ç¯æœ¨é’¢ç´
Tooltip: ""
}
LampWoodSink: {
- DisplayName: Lamp Wood Sink
+ DisplayName: ç¯æœ¨æ°´æ§½
Tooltip: ""
}
LampWoodSofa: {
- DisplayName: Lamp Wood Sofa
+ DisplayName: ç¯æœ¨æ²™å‘
Tooltip: ""
}
LampWoodTable: {
- DisplayName: Lamp Wood Table
+ DisplayName: ç¯æœ¨æ¡Œ
Tooltip: ""
}
LampWoodToilet: {
- DisplayName: Lamp Wood Toilet
+ DisplayName: ç¯æœ¨é©¬æ¡¶
Tooltip: ""
}
LampWood_Chest_Item: {
- DisplayName: Lamp Wood_ Chest_ Item
+ DisplayName: ç¯æœ¨ç®±
Tooltip: ""
}
LampWood_Platform: {
- DisplayName: Lamp Wood_ Platform
+ DisplayName: ç¯æœ¨å¹³å°
Tooltip: ""
}
LampWood_workBench: {
- DisplayName: Lamp Wood_work Bench
+ DisplayName: ç¯æœ¨å·¥ä½œå°
Tooltip: ""
}
HeatproofBathtub_item: {
- DisplayName: Heatproof Bathtub_item
+ DisplayName: éš”çƒæµ´ç¼¸
Tooltip: ""
}
HeatproofBed_item: {
- DisplayName: Heatproof Bed_item
+ DisplayName: éš”çƒåºŠ
Tooltip: ""
}
HeatproofBookcase_item: {
- DisplayName: Heatproof Bookcase_item
+ DisplayName: éš”çƒä¹¦æž¶
Tooltip: ""
}
HeatproofCandelabra_item: {
- DisplayName: Heatproof Candelabra_item
+ DisplayName: éš”çƒçƒ›å°
Tooltip: ""
}
HeatproofCandle_item: {
- DisplayName: Heatproof Candle_item
+ DisplayName: éš”çƒèœ¡çƒ›
Tooltip: ""
}
HeatproofChair_item: {
- DisplayName: Heatproof Chair_item
+ DisplayName: éš”çƒæ¤…
Tooltip: ""
}
HeatproofChandelier_item: {
- DisplayName: Heatproof Chandelier_item
+ DisplayName: éš”çƒåŠç¯
Tooltip: ""
}
HeatproofChest_item: {
- DisplayName: Heatproof Chest_item
+ DisplayName: éš”çƒç®±
Tooltip: ""
}
HeatproofClock_item: {
- DisplayName: Heatproof Clock_item
+ DisplayName: éš”çƒé’Ÿ
Tooltip: ""
}
HeatproofDoor_item: {
- DisplayName: Heatproof Door_item
+ DisplayName: éš”çƒé—¨
Tooltip: ""
}
HeatproofDresser_item: {
- DisplayName: Heatproof Dresser_item
+ DisplayName: éš”çƒæ¢³å¦†å°
Tooltip: ""
}
HeatproofLamp_item: {
- DisplayName: Heatproof Lamp_item
+ DisplayName: éš”çƒç¯
Tooltip: ""
}
HeatproofLantern_item: {
- DisplayName: Heatproof Lantern_item
+ DisplayName: éš”çƒç¯ç¬¼
Tooltip: ""
}
HeatproofPiano_item: {
- DisplayName: Heatproof Piano_item
+ DisplayName: éš”çƒé’¢ç´
Tooltip: ""
}
HeatproofSink_item: {
- DisplayName: Heatproof Sink_item
+ DisplayName: éš”çƒæ°´æ§½
Tooltip: ""
}
HeatproofSofa_item: {
- DisplayName: Heatproof Sofa_item
+ DisplayName: éš”çƒæ²™å‘
Tooltip: ""
}
HeatproofTable_item: {
- DisplayName: Heatproof Table_item
+ DisplayName: éš”çƒæ¡Œ
Tooltip: ""
}
HeatproofToilet_item: {
- DisplayName: Heatproof Toilet_item
+ DisplayName: éš”çƒé©¬æ¡¶
Tooltip: ""
}
HeatproofWorkbench_item: {
- DisplayName: Heatproof Workbench_item
+ DisplayName: éš”çƒå·¥ä½œå°
Tooltip: ""
}
SquamousShellRelic: {
- DisplayName: Squamous Shell Relic
+ DisplayName: 龙鳞å¤å£³åœ£ç‰©
Tooltip: ""
}
SquamousShellTrophy: {
- DisplayName: Squamous Shell Trophy
+ DisplayName: 龙鳞å¤å£³çºªå¿µç«
Tooltip: ""
}
KelpMoss_largeCreate: {
- DisplayName: Kelp Moss_large Create
- Tooltip: ""
+ DisplayName: 放置大型雨帘苔
+ Tooltip: "å¼€å‘者物å“"
}
AlgaeExtractor_Item: {
- DisplayName: Algae Extractor_ Item
+ DisplayName: 藻类æå–机
Tooltip: ""
}
DarklakeBottomMud_Item: {
- DisplayName: Darklake Bottom Mud_ Item
+ DisplayName: 暗湖底泥
Tooltip: ""
}
DecayingWood_Item: {
- DisplayName: Decaying Wood_ Item
+ DisplayName: 朽木
Tooltip: ""
}
DevilHeartIronOre_Item: {
- DisplayName: Devil Heart Iron Ore_ Item
+ DisplayName: é”心é“矿
Tooltip: ""
}
DragonScaleWood: {
- DisplayName: Dragon Scale Wood
+ DisplayName: 龙鳞木
Tooltip: ""
}
GeyserAirBudsItem: {
- DisplayName: Geyser Air Buds Item
+ DisplayName: é—´æ‡æ³‰æ°”苞
Tooltip: ""
}
GreenCourtBrick_Item: {
- DisplayName: Green Court Brick_ Item
+ DisplayName: 绿王åºç –
Tooltip: ""
}
JadeizedBone_Item: {
- DisplayName: Jadeized Bone_ Item
+ DisplayName: 玉化龙骨
Tooltip: ""
}
MossProneSandSoil: {
- DisplayName: Moss Prone Sand Soil
+ DisplayName: è‹”åŸºç ‚åœŸ
Tooltip: ""
}
OldMoss: {
- DisplayName: Old Moss
+ DisplayName: å¤è‹”
Tooltip: ""
}
YggdrasilCyatheaWood: {
- DisplayName: Yggdrasil Cyathea Wood
+ DisplayName: 天穹桫椤
Tooltip: ""
}
DragonScaleWoodWall_Item: {
- DisplayName: Dragon Scale Wood Wall_ Item
+ DisplayName: 龙鳞木墙
Tooltip: ""
}
GreenCourtWall_Item: {
- DisplayName: Green Court Wall_ Item
+ DisplayName: 绿王åºç –墙
Tooltip: ""
}
CyanWindGranite: {
- DisplayName: Cyan Wind Granite
+ DisplayName: é’风岗岩
Tooltip: ""
}
BloodLightCrystal: {
- DisplayName: Blood Light Crystal
+ DisplayName: 血解光石
Tooltip: ""
}
LiftLamp: {
- DisplayName: Lift Lamp
+ DisplayName: 电梯ç¯
Tooltip: ""
}
LiftWinch: {
- DisplayName: Lift Winch
+ DisplayName: 电梯绞盘
Tooltip: ""
}
YggdrasilGrayRock_Item: {
- DisplayName: Yggdrasil Gray Rock_ Item
+ DisplayName: 天穹ç°å²©
Tooltip: ""
}
YggdrasilWorldPylon_Item: {
- DisplayName: Yggdrasil World Pylon_ Item
+ DisplayName: åŽŸåˆæ™¶å¡”
Tooltip: ""
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Potions.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Potions.hjson
index 795f1fd71..bee8cb40e 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Potions.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Potions.hjson
@@ -1,19 +1,19 @@
EnergyDrink: {
- DisplayName: Energy Drink
+ DisplayName: 能é‡é¥®æ–™
Tooltip: ""
}
ShadowPotion: {
- DisplayName: Shadow Potion
+ DisplayName: æš—å½±è¯å‰‚
Tooltip: ""
}
GuidePotion: {
- DisplayName: Guide Potion
+ DisplayName: å¼•è·¯è¯æ°´
Tooltip: ""
}
RayPotion: {
- DisplayName: Ray Potion
+ DisplayName: éœžå…‰è¯æ°´
Tooltip: ""
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.SummonItems.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.SummonItems.hjson
index 0a8d75541..2f2196b12 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.SummonItems.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.SummonItems.hjson
@@ -1,9 +1,9 @@
EvilCocoon: {
- DisplayName: Evil Cocoon
+ DisplayName: 邪茧
Tooltip: ""
}
JellyBallDaifuku: {
- DisplayName: Jelly Ball Daifuku
+ DisplayName: çƒå†»å¤§ç¦
Tooltip: ""
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Tools.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Tools.hjson
index e26a34c58..59fdae473 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Tools.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Tools.hjson
@@ -1,64 +1,64 @@
DragonScaleHammer: {
- DisplayName: Dragon Scale Hammer
+ DisplayName: 龙鳞木锤
Tooltip: ""
}
LampWoodHammer: {
- DisplayName: Lamp Wood Hammer
+ DisplayName: ç¯æœ¨é”¤
Tooltip: ""
}
AmberFlowerHook: {
- DisplayName: Amber Flower Hook
+ DisplayName: ç¥ç€èб钩
Tooltip: ""
}
ClimbingPickaxe: {
- DisplayName: Climbing Pickaxe
+ DisplayName: 攀爬é•
Tooltip: ""
}
CyanVineAxe: {
- DisplayName: Cyan Vine Axe
+ DisplayName: é’缎斧
Tooltip: ""
}
CyanVineHammer: {
- DisplayName: Cyan Vine Hammer
+ DisplayName: é’缎锤
Tooltip: ""
}
CyanVinePickaxe: {
- DisplayName: Cyan Vine Pickaxe
+ DisplayName: é’缎é•
Tooltip: ""
}
FlappedHangGlider: {
- DisplayName: Flapped Hang Glider
+ DisplayName: æŠ˜æŸæ»‘翔翼
Tooltip: ""
}
GlowstickLauncher: {
- DisplayName: Glowstick Launcher
+ DisplayName: è§å…‰æ£’å‘射器
Tooltip: ""
}
HangGlider: {
- DisplayName: Hang Glider
+ DisplayName: 滑翔翼
Tooltip: ""
}
MiningPowerPickaxe: {
- DisplayName: Mining Power Pickaxe
+ DisplayName: 矿用动力é•
Tooltip: ""
}
OldPickaxe: {
- DisplayName: Old Pickaxe
+ DisplayName: æ—§é•
Tooltip: ""
}
OldPortableLamp: {
- DisplayName: Old Portable Lamp
+ DisplayName: æ—§æç¯
Tooltip: ""
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.TreasureBags.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.TreasureBags.hjson
index ecd236a66..c2308f697 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.TreasureBags.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.TreasureBags.hjson
@@ -1,14 +1,14 @@
TuskTreasureBag: {
- DisplayName: Tusk Treasure Bag
+ DisplayName: 鲜血ç 牙å®è—袋
Tooltip: ""
}
CorruptMothTreasureBag: {
- DisplayName: Corrupt Moth Treasure Bag
+ DisplayName: è…æª€å·¨è›¾å®è—袋
Tooltip: ""
}
SquamousShellTreasureBag: {
- DisplayName: Squamous Shell Treasure Bag
+ DisplayName: 龙鳞å¤å£³å®è—袋
Tooltip: ""
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Vanity.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Vanity.hjson
index 8d66d8c88..3fdddd152 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Vanity.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Vanity.hjson
@@ -1,4 +1,4 @@
Acytaea_horn: {
- DisplayName: Acytaea_horn
+ DisplayName: 雅斯塔亚的角
Tooltip: ""
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Weapons.Magic.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Weapons.Magic.hjson
index 1a889f0eb..92731771c 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Weapons.Magic.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Weapons.Magic.hjson
@@ -14,179 +14,214 @@ FeatheredStaff: {
CyanAmberStaff: {
DisplayName: é’ç¼Žæ•´æµæ–
+ Tooltip: å‘å°„æ··åˆäº†é’缎能é‡å’Œå¤©ç©¹ç¥ç€çš„ä¸ç¨³å®šç‰©è´¨å›¢å—
}
HandholdItem: {
- DisplayName: Handhold Item
+ DisplayName: 手æŒå¼ç‰©å“
Tooltip: ""
}
CreamChocolateCupStaff: {
- DisplayName: Cream Chocolate Cup Staff
- Tooltip: ""
+ DisplayName: å¥¶æ²¹å·§å…‹åŠ›æ¯æ³•æ–
+ Tooltip:
+ '''
+ å‘å°„ä¸åŒå½¢çŠ¶çš„å·§å…‹åŠ›å—
+ å³é”®å¯ä»¥ç”¨è¾ƒå¤§çš„æŽ¨åŠ›æŒ¤å‡ºä¸€æ¡å¥¶æ²¹
+ '''
}
FrostBomb: {
- DisplayName: Frost Bomb
- Tooltip: ""
+ DisplayName: 寒霜炸弹
+ Tooltip:
+ '''
+ 左键å‘å°„è½åœ°å³çˆ†çš„å°ç‚¸å¼¹
+ å³é”®å‘射需è¦å°ç‚¸å¼¹è§¦å‘或接触敌人æ‰çˆ†ç‚¸çš„大炸弹
+ çˆ†ç‚¸ä¼šç»™é™„è¿‘æ•Œäººé™„åŠ éœœç«
+ '''
}
ToothMagicBall: {
- DisplayName: Tooth Magic Ball
- Tooltip: ""
+ DisplayName: ç 牙法çƒ
+ Tooltip: "å‘射血团"
}
DreamWeaver: {
- DisplayName: Dream Weaver
- Tooltip: ""
+ DisplayName: 织梦ä¸é›¨
+ Tooltip: "ç¼–é€ è“è‰²çš„é›¨ä¸æ”»å‡»æ•Œäºº"
}
DustOfCorrupt: {
- DisplayName: Dust Of Corrupt
- Tooltip: ""
+ DisplayName: è…化粉尘
+ Tooltip: "喷出æŸç§å¤œå…‰é³žç¿…目的翅膀上的粉末,æ®è¯´ä¼šå¯¼è‡´è¿‡æ•"
}
FlowLightMissile: {
- DisplayName: Flow Light Missile
- Tooltip: ""
+ DisplayName: æµå…‰å¯¼å¼¹
+ Tooltip: "å‘射直线轨迹的爆裂晶体,蓄力使å¨åŠ›æå‡"
}
GlowBeadGun: {
- DisplayName: Glow Bead Gun
- Tooltip: ""
+ DisplayName: è§å…‰è¿žç ç‚®
+ Tooltip: "蓄力以å‘å°„ä¸€è¿žä¸²çš„çˆ†ç ´å"
}
NavyThunder: {
- DisplayName: Navy Thunder
- Tooltip: ""
+ DisplayName: è“焰炸雷
+ Tooltip: "从黑色骷髅嘴里喷出è“色爆弹,需è¦ä¸€å®šæ—¶é—´æ‰ä¼šçˆ†ç‚¸"
}
LilyHarp: {
- DisplayName: Lily Harp
- Tooltip: ""
+ DisplayName: 铃兰竖ç´
+ Tooltip: "å¼¹å¥ä¼šè¿½è¸ªçš„音符"
}
BoneFeatherMagic: {
- DisplayName: Bone Feather Magic
- Tooltip: ""
+ DisplayName: éª¨ç¾½é”æ³•书
+ Tooltip: "è®°è½½ç€æŠŠéª¨ç¾½å½“ä½œé£žé•–å‘射的法术"
}
DarkFlower: {
- DisplayName: Dark Flower
- Tooltip: ""
+ DisplayName: 暗之花
+ Tooltip: "射出暗影çƒ"
}
FeatherMagic: {
- DisplayName: Feather Magic
- Tooltip: ""
+ DisplayName: ç¾½é”æ³•书
+ Tooltip: "è®°è½½ç€æŠŠç¾½æ¯›å½“ä½œé£žé•–å‘射的法术"
}
FireFeatherMagic: {
- DisplayName: Fire Feather Magic
- Tooltip: ""
+ DisplayName: ç«ç¾½é”法书
+ Tooltip: "è®°è½½ç€æŠŠç«ç¾½å½“作飞镖å‘射的法术"
}
FreezeFeatherMagic: {
- DisplayName: Freeze Feather Magic
- Tooltip: ""
+ DisplayName: å†°ç¾½é”æ³•书
+ Tooltip: "è®°è½½ç€æŠŠå†°ç¾½å½“ä½œé£žé•–å‘射的法术"
}
ThunderFlower: {
- DisplayName: Thunder Flower
- Tooltip: ""
+ DisplayName: 雷之花
+ Tooltip: "射出电光çƒ"
}
LanternBombRemoteControl: {
- DisplayName: Lantern Bomb Remote Control
- Tooltip: ""
+ DisplayName: ç¯ç¬¼é¥æŽ§å™¨
+ Tooltip: "å¼€å‘者物å“,内å«é«˜èƒ½ç‚¸å¼¹ï¼Œä¸æ°å½“使用å¯èƒ½ä¼šå¯¼è‡´æ¯å›¾"
}
AmberMagicOrb: {
- DisplayName: Amber Magic Orb
- Tooltip: ""
+ DisplayName: 天ç¥ç€æ³•çƒ
+ Tooltip: "å‘射若干个ç¥ç€ç ,ç¥ç€ç 容易与其他ç¥ç€ç 粘连"
}
BloodySwamp: {
- DisplayName: Bloody Swamp
- Tooltip: ""
+ DisplayName: 浸血泥沼
+ Tooltip:
+ '''
+ å‘射法术模拟的血æµ
+ å³é”®æ¶ˆè€—40法力å‘å°„ä¸€ä¸ªåŠ é€Ÿå›žè¡€çš„åœ†å½¢é¢†åŸŸ
+ '''
}
HexaCrystalStaff: {
- DisplayName: Hexa Crystal Staff
- Tooltip: ""
+ DisplayName: å…æ£±çŸ³èбæ–
+ Tooltip:
+ '''
+ 射出能分裂æˆ6个的è“è‰²æš®å…‰æ™¶ä½“é£žå¼¹ï¼Œé™„åŠ æš®å…‰æ™¶ä½“è„†å¼±
+ '''
}
MagicOfLightAndShadow: {
- DisplayName: Magic Of Light And Shadow
- Tooltip: ""
+ DisplayName: ç¯å½±æˆæ³•
+ Tooltip: "å‘å°„ä¸€æŸæ©˜é»„色光线,且能åå°„2æ¬¡ï¼Œæ¯æ¬¡åå°„å¨åŠ›å‡åŠ"
}
NightfireStaff: {
- DisplayName: Nightfire Staff
- Tooltip: ""
+ DisplayName: å¤œç«æ³•æ–
+ Tooltip: "射出夜ç«é£žå¼¹"
}
RockQuake: {
- DisplayName: Rock Quake
- Tooltip: ""
+ DisplayName: é‡å²©çˆ†è£‚
+ Tooltip: "å‘射一æŸåŠ›åœºï¼Œä¸ä¼šç›´æŽ¥é€ æˆä¼¤å®³ï¼Œä½†æ˜¯ç©¿é€å®žä½“æ–¹å—æ—¶ä¼šä»Žæ–¹å—内部长出尖刺"
}
SmeltingStaff: {
- DisplayName: Smelting Staff
- Tooltip: ""
+ DisplayName: 熔炼法æ–
+ Tooltip: "æ‰‹æŒæ—¶å‘¨å›´ç«‹å³ç”Ÿæˆä¸€ä¸ªèƒ½ç‚¹ç‡ƒæ•Œäººçš„岩浆法环,在环内点击å³å¯è½°ç‚¸"
}
YggdrasilAmberLaser: {
- DisplayName: Yggdrasil Amber Laser
- Tooltip: ""
+ DisplayName: 天ç¥ç€å…‰æŸ
+ Tooltip:
+ '''
+ å‘射一æŸç¥ç€è‰²çš„æ¿€å…‰ï¼Œå‡»ä¸å®žä½“æ–¹å—åŽä¼šåœ¨ä¸Šé¢äº§ç”Ÿç¥ç€ç»“æ™¶
+ ç¥ç€ç»“æ™¶ä¹Ÿèƒ½å¯¹è·¯è¿‡æ»´äººé€ æˆä¼¤å®³
+ '''
}
EyeOfAnabiosis: {
- DisplayName: Eye Of Anabiosis
- Tooltip: ""
+ DisplayName: éšç”Ÿä¹‹çœ¼
+ Tooltip:
+ '''
+ 手æŒå³å¼€å§‹å……能,12ç§’åŽå¯ä»¥æ”»å‡»
+ å‘å°„é’è“色追踪ç«ç„°
+ å¯ä»¥åŒæ—¶æ”»å‡»3ä¸ªç›®æ ‡
+ '''
}
FlurryingBlades: {
- DisplayName: Flurrying Blades
- Tooltip: ""
+ DisplayName: 微风之刃
+ Tooltip: "从书页ä¸å·èµ·ä¸€ä¸ªé£Žåˆƒçƒï¼Œå¯¹è¿‘è·ç¦»ç›®æ ‡é€ æˆå¤šæ®µä¼¤å®³"
}
VitalizedRocks: {
- DisplayName: Vitalized Rocks
- Tooltip: ""
+ DisplayName: æ˜¾ç”Ÿå²©æ ¸
+ Tooltip: "ä»Žè™šç©ºä¸æž„é€ å‡ºå¤§å°ä¸ä¸€çš„岩石éšåŽæŠ•æŽ·"
}
BronzeLotusLamp: {
- DisplayName: Bronze Lotus Lamp
- Tooltip: ""
+ DisplayName: é’铜莲花ç¯
+ Tooltip: "å–·å°„é’莲地心ç«ï¼Œæœ‰æ¦‚率å‘射会爆炸的é’ç«èŠ±è•¾"
}
LightBeamStaff: {
- DisplayName: Light Beam Staff
- Tooltip: ""
+ DisplayName: ç¯æŸæ³•æ–
+ Tooltip:
+ '''
+ å‘射一æŸå…‰ï¼Œé™„带光解效果,击ä¸ç‰©å—åŽç•™ä¸‹ç…§æ˜Žä¿¡æ ‡
+ "ç¯æŸç¬”ç›´ï¼Œåƒæžäº†åˆæ¥ä¹åˆ°è€…çš„å‘å¾€"
+ '''
}
CyanVineStaff: {
- DisplayName: Cyan Vine Staff
- Tooltip: ""
+ DisplayName: é’缎法æ–
+ Tooltip: "使用é’缎å‡å—进行简å•的法术攻击"
}
AncientSyringe: {
- DisplayName: Ancient Syringe
- Tooltip: ""
+ DisplayName: 夿—§çš„æ³¨å°„器
+ Tooltip: "往敌人体内注射感染性å¢å"
}
BacterialAgent: {
- DisplayName: Bacterial Agent
- Tooltip: ""
+ DisplayName: ç»†èŒæº¶æ¶²ç“¶
+ Tooltip: "æŠ•æŽ·å‡ºåŽ»åŽæ•£æ¥æ„ŸæŸ“性å¢å"
}
DevilHeartStaff: {
- DisplayName: Devil Heart Staff
- Tooltip: ""
+ DisplayName: é”心法æ–
+ Tooltip: "攻击8次åŽä¸‹æ¬¡æ”»å‡»ä¸ºç‰¹æ®Šæ”»å‡»ï¼Œå¨åŠ›åŠ å¤§ä¸”é™„å¸¦å‡‹äº¡æŸä¼¤"
}
SightOfTile: {
- DisplayName: Sight Of Tile
- Tooltip: ""
+ DisplayName: 物å—记录器
+ Tooltip:
+ '''
+ å¼€å‘者物å“,也供建ç‘家使用,å…许编辑物å—地图
+ 已具有较完善的GUI和引导系统
+ è¦å‘Šï¼šè¯·å‹¿ç”¨äºŽåˆ‡å‰²ç®±å
+ '''
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Weapons.Melee.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Weapons.Melee.hjson
index 2bfd041e1..cb4a42839 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Weapons.Melee.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Weapons.Melee.hjson
@@ -9,506 +9,563 @@ RodSpear: {
}
BloodGoldBayonet: {
- DisplayName: Blood Gold Bayonet
- Tooltip: ""
+ DisplayName: 血金刺剑
+ Tooltip:
+ '''
+ 命䏿•ŒäººåŽæœ‰1/25的概率å¸è¡€,å¸è¡€é‡ä¸ºé€ æˆä¼¤å®³çš„30%
+ 命ä¸çš„æ•Œäººæœªæ»ä¹‹å‰,ä½ çš„ç”Ÿå‘½å›žå¤+2
+ å³é”®é‡å‡»ï¼šä»¥è‡ªèº«æŸå¤±15血为代价,对被命ä¸çš„æ•Œäººæ–½åŠ æŒç»3s的嗜血符å°,è¡€é‡‘åˆºå‰‘å‘½ä¸æœ‰ç¬¦å°çš„æ•Œäººé€ æˆå›žè¡€
+ 'æ®ä¸å®Œå…¨ç»Ÿè®¡ï¼Œå¤šæ•°å¸è¡€é¬¼å¹¶ä¸ä¼šå¸å–å²èޱ姆æ±'
+ '''
}
BlossomThorn: {
- DisplayName: Blossom Thorn
- Tooltip: ""
+ DisplayName: 红梅è½
+ Tooltip:
+ '''
+ 产生方å‘éšæœºçš„二级刺锋
+ '兼具美观与锋芒'
+ '''
}
BlueRibbonBayonet: {
- DisplayName: Blue Ribbon Bayonet
+ DisplayName: è“缎带刺剑
Tooltip: ""
}
CopperBayonet: {
- DisplayName: Copper Bayonet
+ DisplayName: 铜刺剑
Tooltip: ""
}
CrutchBayonet: {
- DisplayName: Crutch Bayonet
- Tooltip: ""
+ DisplayName: æ‹åˆºå‰‘
+ Tooltip:
+ '''
+ ç¬¬ä¸€æ¬¡å‘½ä¸æ•ŒäººåŽå¦‚æžœæš´å‡»åˆ™é€ æˆ270%的伤害
+ '特务使用的æ¦å™¨ï¼Œéžå¸¸é€‚åˆæš—æ€'
+ '''
}
CurseFlameStabbingSword: {
- DisplayName: Curse Flame Stabbing Sword
- Tooltip: ""
+ DisplayName: å’’ç«åˆºå‰‘
+ Tooltip: "用诅咒ç«ç„°ç‚¹ç‡ƒæ•Œäººï¼"
}
DreamStar: {
- DisplayName: Dream Star
- Tooltip: ""
+ DisplayName: 梦辰星刺
+ Tooltip:
+ '''
+ æ¯æ¬¡å‘½ä¸éƒ½ä¼šç»™æ•Œäººæ ‡ä¸Š1层[è§’æ˜Ÿæ ‡]
+ 5层[è§’æ˜Ÿæ ‡]åˆæˆä¸€ä¸ª[æ˜Ÿæ ‡],获得[æ˜Ÿæ ‡]的敌人ä¸ä¼šå†èŽ·å¾—æ›´å¤š[è§’æ˜Ÿæ ‡]
+ 对于åŒä¸€æŠŠ[梦辰星刺],场上最多å˜åœ¨ä¸¤ä¸ªè¢«[æ˜Ÿæ ‡]或角[æ˜Ÿæ ‡]æ ‡è®°çš„æ•Œäºº
+ 两个[æ˜Ÿæ ‡]çš„å‡ºçŽ°ä¼šåœ¨ä¸¤å¤„åŒæ—¶å¼•å‘220%å€çŽ‡çš„æ˜Ÿè¾‰çˆ†ç‚¸ï¼Œå¹¶æ‘§æ¯å…ˆè¢«æ ‡è®°çš„æ•Œäººçš„[æ˜Ÿæ ‡]
+ ç›®æ ‡æ•Œäººè‹¥æ²¡æœ‰[æ˜Ÿæ ‡],且场上已å˜åœ¨è¢«ä½ 命ä¸è¿‡ä½†æ˜¯[è§’æ˜Ÿæ ‡]ä¸è¶³5ä¸ªçš„æ•Œäººï¼Œä¹Ÿä¼šåœ¨ç›®æ ‡æ•Œäººå’Œè¢«[è§’æ˜Ÿæ ‡]æ ‡è®°çš„è§’è‰²å¤„å¼•å‘较å°çš„æ˜Ÿè¾‰çˆ†ç‚¸ï¼Œå¨åŠ›å–决于[è§’æ˜Ÿæ ‡]层数
+ 带有[æ˜Ÿæ ‡]的敌人被击æ€ä¼šæŽ‰è½æ˜Ÿä¹‹ç§ï¼Œæ‹¾å–åŽä¸‹æ¬¡é€ æˆä¼¤å®³å¿…定暴击且伤害*264%
+ '读懂星空需è¦å¤æ‚深邃的ç†è®ºçŸ¥è¯†ï¼Œè§‚èµæ˜Ÿç©ºåªéœ€è¦ä¸€åªçœ¼ç›'
+ '''
}
EnchantedBayonet: {
- DisplayName: Enchanted Bayonet
- Tooltip: ""
+ DisplayName: 附é”刺剑
+ Tooltip: "å³é”®é‡å‡»ä¼šæ”¾å‡ºä¸å—é‡åŠ›çš„å‰‘æ°”"
}
EternalNight: {
- DisplayName: Eternal Night
- Tooltip: ""
+ DisplayName: 永夜刺剑
+ Tooltip: "击ä¸åŽå¯ä»¥é‡Šæ”¾è¿½é‚影刺剑"
}
GoldenStabbingSword: {
- DisplayName: Golden Stabbing Sword
+ DisplayName: 金刺剑
Tooltip: ""
}
HolyBayonet: {
- DisplayName: Holy Bayonet
+ DisplayName: 神圣刺剑
Tooltip: ""
}
IchorBayonet: {
- DisplayName: Ichor Bayonet
+ DisplayName: çµæ¶²åˆºå‰‘
Tooltip: ""
}
IronStabbingSword: {
- DisplayName: Iron Stabbing Sword
+ DisplayName: é“刺剑
Tooltip: ""
}
LeadStabbingSword: {
- DisplayName: Lead Stabbing Sword
+ DisplayName: 铅刺剑
Tooltip: ""
}
MechanicMosquito: {
- DisplayName: Mechanic Mosquito
- Tooltip: ""
+ DisplayName: 械蚊刺
+ Tooltip: "å¬å”¤ä¸‰ä¸ªä¼šå¸è¡€çš„æœºæ¢°èšŠåå助攻击,èšŠåæ¯æ¬¡æ”»å‡»ä¼šèŽ·å¾—1点å¸è¡€ï¼Œæœ€å¤šç´¯ç§¯10点。使用结æŸä¹‹åŽï¼Œæ²»ç–—å¸è¡€ç´¯ç§¯çš„点数"
}
PlatinumStabbingSword: {
- DisplayName: Platinum Stabbing Sword
+ DisplayName: 铂金刺剑
Tooltip: ""
}
PrisonFireBayonet: {
- DisplayName: Prison Fire Bayonet
- Tooltip: ""
+ DisplayName: 狱ç«åˆºå‰‘
+ Tooltip:
+ '''
+ 点燃敌人ï¼
+ åœ¨æ°´é‡Œæ— æ³•ç‚¹ç‡ƒ,ä½†æ˜¯åœ¨ç†”å²©é‡Œé€ æˆä¸¤å€ä¼¤å®³
+ '切勿伤敌一万自æŸå…«åƒ'
+ '''
}
RedRibbonBayonet: {
- DisplayName: Red Ribbon Bayonet
+ DisplayName: 红缎带刺剑
Tooltip: ""
}
RottenGoldBayonet: {
- DisplayName: Rotten Gold Bayonet
- Tooltip: ""
+ DisplayName: é”金刺剑
+ Tooltip:
+ '''
+ 命ä¸åŽå‰Šå¼±ç›®æ ‡1点防御力
+ 延时一秒在命ä¸å¤„生æˆä¸‰é“200%å€çŽ‡çš„é”金剑光
+ 对于åŒä¸€æŠŠ[é”金刺剑],ä¸Šè¿°ä¸¤ç§æ•ˆæžœ1秒最多触å‘1次,但是总数没有上é™
+ '''
}
SilverStabbingSword: {
- DisplayName: Silver Stabbing Sword
+ DisplayName: 银刺剑
Tooltip: ""
}
SwordfishBeak: {
- DisplayName: Swordfish Beak
- Tooltip: ""
+ DisplayName: 剑鱼长喙
+ Tooltip: "å¯¹äºŽæ°´é‡Œçš„æ•Œäººé€ æˆä¼¤å®³ä¸‹é™40%,但是潮湿状æ€ä¸‹æ”»å‡»èŒƒå›´æ‰©å¤§50%,且体力消耗é™ä½Ž35%,对于干燥的敌人伤害æé«˜40%"
}
TinStabbingSword: {
- DisplayName: Tin Stabbing Sword
+ DisplayName: 锡刺剑
Tooltip: ""
}
TungstenStabbingSword: {
- DisplayName: Tungsten Stabbing Sword
+ DisplayName: 钨刺剑
Tooltip: ""
}
VegetationBayonet: {
- DisplayName: Vegetation Bayonet
- Tooltip: ""
+ DisplayName: 葱èŒåˆºå‰‘
+ Tooltip:
+ '''
+ ä¼šé€ æˆä¸æ¯’
+ 使用6秒之åŽè‡ªå·±ä¹Ÿä¼šå˜å¾—狂野
+ '看到那åªè™è 了å—,它的蛋白质是牛肉的å…å€'
+ '''
}
VertebralSpur: {
- DisplayName: Vertebral Spur
- Tooltip: ""
+ DisplayName: 椎刺骨
+ Tooltip:
+ '''
+ åœ¨ä¸Žç›®æ ‡ç›¸å¯¹é€Ÿåº¦è¾ƒå¤§çš„æƒ…å†µä¸‹æå‡ä¼¤å®³ï¼Œæœ€å¤šä¸è¶…过500%
+ '粗糙的接触é¢é€ æˆçš„æ¯åéšé€Ÿåº¦çš„å¢žåŠ æ€¥å‰§æé«˜'
+ '''
}
YoenLeZed: {
- DisplayName: Yoen Le Zed
- Tooltip: ""
+ DisplayName: 陨雷之劫刺剑
+ Tooltip:
+ '''
+ 攻击附带雷电,水ä¸é›·ç”µä¼¤å®³ç¿»ä¸‰å€ä¸”æ›´å®¹æ˜“ä¼ å¯¼
+ 比考场忘带身份è¯è¿˜åˆºæ¿€ä¸€ç‚¹
+ '''
}
CheeseYoyo: {
- DisplayName: Cheese Yoyo
+ DisplayName: èŠå£«çƒ
Tooltip: ""
}
FryingPanItem: {
- DisplayName: Frying Pan Item
- Tooltip: ""
+ DisplayName: 平底锅
+ Tooltip:
+ '''
+ å³é”®å¯ä»¥é‡å‡»
+ '''
}
VortexVanquisherItem: {
- DisplayName: Vortex Vanquisher Item
- Tooltip: ""
+ DisplayName: 贯虹之槊
+ Tooltip:
+ '''
+ å³é”®å¯ä»¥å¬å”¤[地心],并生æˆå¯ä»¥å¸æ”¶ä¼¤å®³çš„[玉璋护盾]
+ ä¸é”®å¬å”¤[天星]ï¼Œé€ æˆå¤§èŒƒå›´ä¼¤å®³å’ŒçŸ³åŒ–
+ '''
}
PineStab: {
- DisplayName: Pine Stab
- Tooltip: ""
+ DisplayName: æ¾é’ˆåˆº
+ Tooltip:
+ '''
+ åªè€—è´¹72%çš„ä½“åŠ›ï¼Œå› ä¸ºæ¾å¶å¾ˆè½»
+ 所以怪物的防御力3倿œ‰æ•ˆ
+ '''
}
BloodyBoneYoyo: {
- DisplayName: Bloody Bone Yoyo
- Tooltip: ""
+ DisplayName: 血髓çƒ
+ Tooltip: "会伸出触手攻击附近敌人"
}
ToothKnife: {
- DisplayName: Tooth Knife
+ DisplayName: 齿刃
Tooltip: ""
}
ToothSpear: {
- DisplayName: Tooth Spear
+ DisplayName: ç 牙矛
Tooltip: ""
}
GlowWoodSword: {
- DisplayName: Glow Wood Sword
+ DisplayName: æµè¤æœ¨å‰‘
Tooltip: ""
}
MothYoyo: {
- DisplayName: Moth Yoyo
- Tooltip: ""
+ DisplayName: 夜蛾çƒ
+ Tooltip: "æ‚ æ‚ çƒé™„近会有è§å…‰é£žè›¾å¹»æ–¹"
}
ScaleWingBlade: {
- DisplayName: Scale Wing Blade
- Tooltip: ""
+ DisplayName: 鳞翅之刃
+ Tooltip: "å³é”®å¯ä»¥é‡å‡»"
}
ComingGhost: {
- DisplayName: Coming Ghost
- Tooltip: ""
+ DisplayName: 诡弑
+ Tooltip: "æ”»å‡»æ—¶æœ‰æ¦‚çŽ‡ç”¨é¬¼çˆªéšæœºæ— 视è·ç¦»åœ°æ”»å‡»ä¸€ä¸ªæ•Œäºº"
}
CyanFrost: {
- DisplayName: Cyan Frost
- Tooltip: ""
+ DisplayName: é’霜剑
+ Tooltip: "附带霜ç«"
}
Glow: {
- DisplayName: Glow
- Tooltip: ""
+ DisplayName: æµå…‰
+ Tooltip: "ç 出金色剑气并å¬å”¤è½ä¸‹çš„è“色星辉"
}
GoldRoundYoyo: {
- DisplayName: Gold Round Yoyo
+ DisplayName: 金轮çƒ
Tooltip: ""
}
PrimordialJadeWinged_Spear: {
- DisplayName: Primordial Jade Winged_ Spear
- Tooltip: ""
+ DisplayName: 和璞鸢
+ Tooltip: "åœ¨ä¸€å®šé«˜åº¦ä½¿ç”¨æ—¶ä¼šæ”¹ä¸ºä¸‹ç ¸ï¼Œå³é”®å¯ä»¥æœä»»æ„æ–¹å‘çªåˆº"
}
Sunflower: {
- DisplayName: Sunflower
+ DisplayName: 呿—¥é£žç›˜
Tooltip: ""
}
World: {
- DisplayName: World
- Tooltip: ""
+ DisplayName: 世界斩裂
+ Tooltip:
+ '''
+ å³é”®å¯ä»¥åˆ‡æ¢è¿½é𿍡å¼å’Œæ–©åˆ‡æ¨¡å¼
+ è¿½éšæ¨¡å¼ä¸‹[世界斩裂]会åœç•™åœ¨é¼ æ ‡ä½ç½®ï¼Œæ²¿ç€é¼ æ ‡çš„è·¯çº¿åˆ‡å‰²æ•Œäºº
+ 斩切模å¼ä¸‹[世界斩裂]会åå¤å¿«é€Ÿè´¯ç©¿é¼ æ ‡
+ '''
}
AdamantiteClub_Item: {
- DisplayName: Adamantite Club_ Item
- Tooltip: ""
+ DisplayName: ç²¾é‡‘æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
BorealWoodClub_Item: {
- DisplayName: Boreal Wood Club_ Item
- Tooltip: ""
+ DisplayName: çç æœ¨æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
CactusClub_Item: {
- DisplayName: Cactus Club_ Item
- Tooltip: ""
+ DisplayName: ä»™äººæŽŒæ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
ChlorophyteClub_Item: {
- DisplayName: Chlorophyte Club_ Item
- Tooltip: ""
+ DisplayName: å¶ç»¿æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
CobaltClub_Item: {
- DisplayName: Cobalt Club_ Item
- Tooltip: ""
+ DisplayName: é’´æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
CopperClub_Item: {
- DisplayName: Copper Club_ Item
- Tooltip: ""
+ DisplayName: é“œæ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
CorruptClub_Item: {
- DisplayName: Corrupt Club_ Item
- Tooltip: ""
+ DisplayName: é”é‡‘æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
CrimsonClub_Item: {
- DisplayName: Crimson Club_ Item
- Tooltip: ""
+ DisplayName: è¡€é‡‘æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
CrystalClub_Item: {
- DisplayName: Crystal Club_ Item
- Tooltip: ""
+ DisplayName: æ°´æ™¶æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
CurseClub_Item: {
- DisplayName: Curse Club_ Item
- Tooltip: ""
+ DisplayName: å’’ç«æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
EbonwoodClub_Item: {
- DisplayName: Ebonwood Club_ Item
- Tooltip: ""
+ DisplayName: ä¹Œæœ¨æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
GoldClub_Item: {
- DisplayName: Gold Club_ Item
- Tooltip: ""
+ DisplayName: é‡‘æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
IchorClub_Item: {
- DisplayName: Ichor Club_ Item
- Tooltip: ""
+ DisplayName: çµæ¶²æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
IronClub_Item: {
- DisplayName: Iron Club_ Item
- Tooltip: ""
+ DisplayName: 铿£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
LeadClub_Item: {
- DisplayName: Lead Club_ Item
- Tooltip: ""
+ DisplayName: é“…æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
MeteorClub_Item: {
- DisplayName: Meteor Club_ Item
- Tooltip: ""
+ DisplayName: é™¨çŸ³æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
MythrilClub_Item: {
- DisplayName: Mythril Club_ Item
- Tooltip: ""
+ DisplayName: ç§˜é“¶æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
OrichalcumClub_Item: {
- DisplayName: Orichalcum Club_ Item
- Tooltip: ""
+ DisplayName: å±±é“œæ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
PalladiumClub_Item: {
- DisplayName: Palladium Club_ Item
- Tooltip: ""
+ DisplayName: é’¯é‡‘æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
PalmWoodClub_Item: {
- DisplayName: Palm Wood Club_ Item
- Tooltip: ""
+ DisplayName: æ£•æ¦ˆæœ¨æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
PearlwoodClub_Item: {
- DisplayName: Pearlwood Club_ Item
- Tooltip: ""
+ DisplayName: çç æœ¨æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
PlatinumClub_Item: {
- DisplayName: Platinum Club_ Item
- Tooltip: ""
+ DisplayName: é“‚é‡‘æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
RichMahoganyClub_Item: {
- DisplayName: Rich Mahogany Club_ Item
- Tooltip: ""
+ DisplayName: çº¢æœ¨æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
ShadewoodClub_Item: {
- DisplayName: Shadewood Club_ Item
- Tooltip: ""
+ DisplayName: æš—å½±æœ¨æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
SilverClub_Item: {
- DisplayName: Silver Club_ Item
- Tooltip: ""
+ DisplayName: é“¶æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
SpikeClub_Item: {
- DisplayName: Spike Club_ Item
- Tooltip: ""
+ DisplayName: å°–åˆºæ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
StarDancer_Item: {
- DisplayName: Star Dancer_ Item
- Tooltip: ""
+ DisplayName: æ˜Ÿèˆžè€…æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
TinClub_Item: {
- DisplayName: Tin Club_ Item
- Tooltip: ""
+ DisplayName: é”¡æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
TitaniumClub_Item: {
- DisplayName: Titanium Club_ Item
- Tooltip: ""
+ DisplayName: é’›é‡‘æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
TungstenClub_Item: {
- DisplayName: Tungsten Club_ Item
- Tooltip: ""
+ DisplayName: é’¨æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
WoodenClub_Item: {
- DisplayName: Wooden Club_ Item
- Tooltip: ""
+ DisplayName: æœ¨æ£æ£’
+ Tooltip: "一定高度åŽå³é”®å¯ä¸‹ç ¸"
}
Acytaea_sword_Item: {
- DisplayName: Acytaea_sword_ Item
+ DisplayName: 雅斯塔亚的剑
Tooltip: ""
}
CactusBall: {
- DisplayName: Cactus Ball
+ DisplayName: 仙人掌链çƒ
Tooltip: ""
}
AmberHeadedSpear: {
- DisplayName: Amber Headed Spear
+ DisplayName: ç¥ç€çŸ›
Tooltip: ""
}
AmethystHeadedSpear: {
- DisplayName: Amethyst Headed Spear
+ DisplayName: 紫晶矛
Tooltip: ""
}
CeremonialBlade: {
- DisplayName: Ceremonial Blade
+ DisplayName: 仪å¼ä½©åˆ€
Tooltip: ""
}
DarkMassacreDagger: {
- DisplayName: Dark Massacre Dagger
+ DisplayName: æš—é‡‘å± æ€åˆ€
Tooltip: ""
}
MagicalBoomerang: {
- DisplayName: Magical Boomerang
- Tooltip: ""
+ DisplayName: 锿œ¯å›žæ—‹é•–
+ Tooltip: "å‘射出去åŽç‚¹å‡»ä½¿ä¹‹åˆ†è£‚为8个å回旋镖"
}
QuenchingBlade: {
- DisplayName: Quenching Blade
+ DisplayName: æ·¬ç«é’¢ç‰‡
Tooltip: ""
}
ResistanceWireBayonet: {
- DisplayName: Resistance Wire Bayonet
- Tooltip: ""
+ DisplayName: 电阻刺剑
+ Tooltip: "ä¸ä½¿ç”¨æ—¶é€æ¸å……能并æå‡å¨åŠ›ï¼Œå‡»ä¸æ•ŒäººåŽå¤±åŽ»å……èƒ½æ•ˆæžœ"
}
ScarpasScissors: {
- DisplayName: Scarpas Scissors
+ DisplayName: æ–¯å¡å¸•的剪刀
Tooltip: ""
}
TopaztHeadedSpear: {
- DisplayName: Topazt Headed Spear
+ DisplayName: 黄玉矛
Tooltip: ""
}
TwilightEucalyptusBlade: {
- DisplayName: Twilight Eucalyptus Blade
+ DisplayName: 暮桉木刃
Tooltip: ""
}
TwilightEucalyptusBoomerangKnift: {
- DisplayName: Twilight Eucalyptus Boomerang Knift
+ DisplayName: 暮桉木回旋刀
Tooltip: ""
}
TwilightEucalyptusCuffSickle: {
- DisplayName: Twilight Eucalyptus Cuff Sickle
- Tooltip: ""
-}
-
-TwilightShamanStaff: {
- DisplayName: Twilight Shaman Staff
+ DisplayName: 暮桉木袖刃
Tooltip: ""
}
HyperockSpear: {
- DisplayName: Hyperock Spear
+ DisplayName: 天穹岩枪
Tooltip: ""
}
LampWoodSword: {
- DisplayName: Lamp Wood Sword
+ DisplayName: ç¯æœ¨å‰‘
Tooltip: ""
}
LampWoodYoyo: {
- DisplayName: Lamp Wood Yoyo
+ DisplayName: ç¯æœ¨çƒ
Tooltip: ""
}
CyanVineShortsword: {
- DisplayName: Cyan Vine Shortsword
+ DisplayName: é’缎çŸå‰‘
Tooltip: ""
}
CyanVineSword: {
- DisplayName: Cyan Vine Sword
+ DisplayName: é’缎剑
Tooltip: ""
}
BladeOfGreenMoss: {
- DisplayName: Blade Of Green Moss
+ DisplayName: 绿苔之刃
Tooltip: ""
}
MeatLantern: {
- DisplayName: Meat Lantern
+ DisplayName: 肉食性æç¯
Tooltip: ""
}
HandheldCircularSaw: {
- DisplayName: Handheld Circular Saw
+ DisplayName: 手æŒå¼åœ†é”¯
Tooltip: ""
}
AcroporaSpear: {
- DisplayName: Acropora Spear
+ DisplayName: 藻刃矛
Tooltip: ""
}
CharonDoubleSickle_Item: {
- DisplayName: Charon Double Sickle_ Item
+ DisplayName: 碧绿åŒé•°
Tooltip: ""
}
ShadowEulogist: {
- DisplayName: Shadow Eulogist
+ DisplayName: 暗影赞颂者
Tooltip: ""
}
TrueDeathSickle: {
- DisplayName: True Death Sickle
- Tooltip: ""
+ DisplayName: 真·æ»ç¥žé•°åˆ€
+ Tooltip: "用æ»ç«ç‚¹ç‡ƒæ•Œäºº"
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Weapons.Ranged.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Weapons.Ranged.hjson
index c18882fc8..3d7f55b47 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Weapons.Ranged.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Weapons.Ranged.hjson
@@ -5,284 +5,303 @@ RazorbeakBow: {
CyanVineBow: {
DisplayName: é’缎弓
+ Tooltip: ""
}
IcedSpear: {
- DisplayName: Iced Spear
+ DisplayName: 冰尖投矛
Tooltip: ""
}
SpineGun: {
- DisplayName: Spine Gun
+ DisplayName: 脊骨手枪
Tooltip: ""
}
ToothBow: {
- DisplayName: Tooth Bow
- Tooltip: ""
+ DisplayName: ç 牙巨弓
+ Tooltip: "å‘射巨形ç 牙ç®"
}
PhosphorescenceGun: {
- DisplayName: Phosphorescence Gun
+ DisplayName: 磷光枪
Tooltip: ""
}
ShadowWingBow: {
- DisplayName: Shadow Wing Bow
- Tooltip: ""
+ DisplayName: 影翼巨弓
+ Tooltip: "蓄力å‘射更多幻ç®"
}
CloudGun: {
- DisplayName: Cloud Gun
- Tooltip: ""
+ DisplayName: 云导炮
+ Tooltip: "å‘射云团"
}
SilveralGun: {
- DisplayName: Silveral Gun
+ DisplayName: 银影手枪
Tooltip: ""
}
SilveralRifle: {
- DisplayName: Silveral Rifle
+ DisplayName: é“¶å½±æ¥æžª
Tooltip: ""
}
AmbiguousNight: {
- DisplayName: Ambiguous Night
- Tooltip: ""
+ DisplayName: 幻夜弹弓
+ Tooltip: "䏿¶ˆè€—å¼¹è¯ï¼Œè“„力æå‡å¨åŠ›"
}
AmethystSlingshot: {
- DisplayName: Amethyst Slingshot
- Tooltip: ""
+ DisplayName: 紫晶弹弓
+ Tooltip: "䏿¶ˆè€—å¼¹è¯ï¼Œè“„力æå‡å¨åŠ›"
}
BorealWoodSlingshot: {
- DisplayName: Boreal Wood Slingshot
- Tooltip: ""
+ DisplayName: é’ˆå¶æœ¨å¼¹å¼“
+ Tooltip: "䏿¶ˆè€—å¼¹è¯ï¼Œè“„力æå‡å¨åŠ›"
}
CactusSlingShot: {
- DisplayName: Cactus Sling Shot
- Tooltip: ""
+ DisplayName: 仙人掌弹弓
+ Tooltip: "䏿¶ˆè€—å¼¹è¯ï¼Œè“„力æå‡å¨åŠ›"
}
DiamondSlingshot: {
- DisplayName: Diamond Slingshot
- Tooltip: ""
+ DisplayName: 钻石弹弓
+ Tooltip: "䏿¶ˆè€—å¼¹è¯ï¼Œè“„力æå‡å¨åŠ›"
}
EbonwoodSlingshot: {
- DisplayName: Ebonwood Slingshot
- Tooltip: ""
+ DisplayName: 乌木弹弓
+ Tooltip: "䏿¶ˆè€—å¼¹è¯ï¼Œè“„力æå‡å¨åŠ›"
}
EmeraldSlingshot: {
- DisplayName: Emerald Slingshot
- Tooltip: ""
+ DisplayName: 祖æ¯ç»¿å¼¹å¼“
+ Tooltip: "䏿¶ˆè€—å¼¹è¯ï¼Œè“„力æå‡å¨åŠ›"
}
GelSlingshot: {
- DisplayName: Gel Slingshot
- Tooltip: ""
+ DisplayName: å‡èƒ¶å¼¹å¼“
+ Tooltip: "䏿¶ˆè€—å¼¹è¯ï¼Œè“„力æå‡å¨åŠ›"
}
JungleSlingshot: {
- DisplayName: Jungle Slingshot
- Tooltip: ""
+ DisplayName: 丛林弹弓
+ Tooltip: "䏿¶ˆè€—å¼¹è¯ï¼Œè“„力æå‡å¨åŠ›"
}
PalmWoodSlingshot: {
- DisplayName: Palm Wood Slingshot
- Tooltip: ""
+ DisplayName: 棕榈木弹弓
+ Tooltip: "䏿¶ˆè€—å¼¹è¯ï¼Œè“„力æå‡å¨åŠ›"
}
PearlwoodSlingshot: {
- DisplayName: Pearlwood Slingshot
- Tooltip: ""
+ DisplayName: çç æœ¨å¼¹å¼“
+ Tooltip: "䏿¶ˆè€—å¼¹è¯ï¼Œè“„力æå‡å¨åŠ›"
}
RichMahoganySlingshot: {
- DisplayName: Rich Mahogany Slingshot
- Tooltip: ""
+ DisplayName: 红木弹弓
+ Tooltip: "䏿¶ˆè€—å¼¹è¯ï¼Œè“„力æå‡å¨åŠ›"
}
RubySlingshot: {
- DisplayName: Ruby Slingshot
- Tooltip: ""
+ DisplayName: 红å®çŸ³å¼¹å¼“
+ Tooltip: "䏿¶ˆè€—å¼¹è¯ï¼Œè“„力æå‡å¨åŠ›"
}
SapphireSlingshot: {
- DisplayName: Sapphire Slingshot
- Tooltip: ""
+ DisplayName: è“å®çŸ³å¼¹å¼“
+ Tooltip: "䏿¶ˆè€—å¼¹è¯ï¼Œè“„力æå‡å¨åŠ›"
}
ShadewoodSlingShot: {
- DisplayName: Shadewood Sling Shot
- Tooltip: ""
+ DisplayName: 暗影木弹弓
+ Tooltip: "䏿¶ˆè€—å¼¹è¯ï¼Œè“„力æå‡å¨åŠ›"
}
StarSlingshot: {
- DisplayName: Star Slingshot
- Tooltip: ""
+ DisplayName: 星星弹弓
+ Tooltip: "䏿¶ˆè€—å¼¹è¯ï¼Œè“„力æå‡å¨åŠ›"
}
TopazSlingshot: {
- DisplayName: Topaz Slingshot
- Tooltip: ""
+ DisplayName: 黄玉弹弓
+ Tooltip: "䏿¶ˆè€—å¼¹è¯ï¼Œè“„力æå‡å¨åŠ›"
}
WoodSlingshot: {
- DisplayName: Wood Slingshot
- Tooltip: ""
+ DisplayName: 木弹弓
+ Tooltip: "䏿¶ˆè€—å¼¹è¯ï¼Œè“„力æå‡å¨åŠ›"
}
CloudBall: {
- DisplayName: Cloud Ball
+ DisplayName: 云团
Tooltip: ""
}
RampageShark: {
- DisplayName: Rampage Shark
- Tooltip: ""
+ DisplayName: å¤ä»‡é²¨
+ Tooltip: "使用一定时间åŽè¿‡çƒï¼Œå°„速æå‡ä½†æ˜¯å‡†åº¦ä¸‹é™"
}
TsunamiShark: {
- DisplayName: Tsunami Shark
- Tooltip: ""
+ DisplayName: 海啸鲨
+ Tooltip:
+ '''
+ å³é”®å¯ä»¥æ ‡è®°æ•Œäºº
+ 击䏿•ŒäººåŽç”Ÿæˆé²¨é±¼å¯¼å¼¹
+ å¯¼å¼¹ä¼šè¾…åŠ©æ”»å‡»è¢«æ ‡è®°æ•Œäºº
+ '''
}
ArmorPiercingBlaster: {
- DisplayName: Armor Piercing Blaster
- Tooltip: ""
+ DisplayName: ç©¿ç”²çˆ†ç ´å
+ Tooltip: "丢出去åŽåœ¨æ•Œäººé è¿‘æ—¶æ‰çˆ†ç‚¸ï¼Œå‰Šå‡å…¶é˜²å¾¡åŠ›10ç§’"
}
Caltrop: {
- DisplayName: Caltrop
+ DisplayName: é“蒺藜
Tooltip: ""
}
CeremonialRifle: {
- DisplayName: Ceremonial Rifle
+ DisplayName: 仪å¼ç”¨æžª
Tooltip: ""
}
GunOfAvarice: {
- DisplayName: Gun Of Avarice
- Tooltip: ""
+ DisplayName: 贪婪之铳
+ Tooltip:
+ '''
+ æ¯æ‰“完14å‘å弹进行一次弹匣更æ¢(45帧)ï¼ŒæœŸé—´æ— æ³•æ”»å‡»
+ å¼¹åŒ£æ›´æ¢æˆåŠŸçŽ‡ä¸º80%
+ æˆåŠŸï¼šå¼¹åŒ£æ›´æ¢åŽç‰çº§+1ä¼¤å®³è¾ƒä¹‹å‰æå‡25%
+ 失败:爆炸并å—åˆ°é¢æ¿ä¼¤å®³çš„2.8å€ä¼¤å®³
+ æˆåŠŸæ•ˆæžœæœ€å¤šè¾¾åˆ°10级。
+ å³é”®æ‰‹åŠ¨æ›´æ¢å¼¹åŒ£å¹¶ä½¿å¼¹åŒ£ç‰çº§æ¸…é›¶
+ æ¯æ¬¡å‘½ä¸è®©æ•Œäººä»·å€¼+75铜
+ '''
}
Nehemoth: {
- DisplayName: Nehemoth
- Tooltip: ""
+ DisplayName: 低è¯è€…
+ Tooltip:
+ '''.
+ å°†ç«æžªåå¼¹å˜æˆé«˜é€Ÿç‰¹æ®Šå¼¹å¹•ï¼Œæ— é™ç©¿é€ï¼Œå‘½ä¸çš„生物有66%的概率获得瘟疫Debuff4ç§’
+ 瘟疫能在敌人之间散æ¥ï¼Œé€ æˆç¾¤ä½“è¡€é‡æµå¤±
+ '''
}
RustSlingshot: {
- DisplayName: Rust Slingshot
+ DisplayName: 生锈弹弓
Tooltip: ""
}
SevenShotGun: {
- DisplayName: Seven Shot Gun
+ DisplayName: 七å‘猎枪
Tooltip: ""
}
StoneJavelin: {
- DisplayName: Stone Javelin
+ DisplayName: 岩石投矛
Tooltip: ""
}
RockSpikeBallista: {
- DisplayName: Rock Spike Ballista
+ DisplayName: 碎裂投石
Tooltip: ""
}
BrittleRockSlingshot: {
- DisplayName: Brittle Rock Slingshot
+ DisplayName: 碎石弹弓
Tooltip: ""
}
KissOfCthulhu: {
- DisplayName: Kiss Of Cthulhu
+ DisplayName: å…‹è‹é²ä¹‹å»
Tooltip: ""
}
BowOfEnlightment: {
- DisplayName: Bow Of Enlightment
+ DisplayName: 坿˜Žä¹‹å¼“
Tooltip: ""
}
HandgunOfEnlightment: {
- DisplayName: Handgun Of Enlightment
+ DisplayName: 坿˜Žæ‰‹æžª
Tooltip: ""
}
LampWoodBow: {
- DisplayName: Lamp Wood Bow
+ DisplayName: ç¯æœ¨å¼“
Tooltip: ""
}
CyanVineCrossBow: {
- DisplayName: Cyan Vine Cross Bow
+ DisplayName: é’缎弩
Tooltip: ""
}
CyanVineFlintlock: {
- DisplayName: Cyan Vine Flintlock
+ DisplayName: é’ç¼Žç‡§å‘æžª
Tooltip: ""
}
CyanVineThrowingSpear: {
- DisplayName: Cyan Vine Throwing Spear
+ DisplayName: é’缎投矛
Tooltip: ""
}
CaterpillarJuiceArrow: {
- DisplayName: Caterpillar Juice Arrow
+ DisplayName: 虫æ±ç®
Tooltip: ""
}
LightArrow: {
- DisplayName: Light Arrow
+ DisplayName: ç¯æ²¹ç®
Tooltip: ""
}
LightBullet: {
- DisplayName: Light Bullet
+ DisplayName: ç¯æ²¹å¼¹
Tooltip: ""
}
RockArrow: {
- DisplayName: Rock Arrow
+ DisplayName: 岩甲é‡ç®
Tooltip: ""
}
GreenThornBallLauncher: {
- DisplayName: Green Thorn Ball Launcher
+ DisplayName: é’刺çƒå‘射器
Tooltip: ""
}
MossyCyatheaBow: {
- DisplayName: Mossy Cyathea Bow
+ DisplayName: é’苔桫椤弓
Tooltip: ""
}
DevilHeartBow: {
- DisplayName: Devil Heart Bow
+ DisplayName: é”心é“弓
Tooltip: ""
}
DevilHeartGun: {
- DisplayName: Devil Heart Gun
+ DisplayName: é”心手枪
Tooltip: ""
}
CyatheaArrow: {
- DisplayName: Cyathea Arrow
+ DisplayName: 桫椤ç®
Tooltip: ""
}
TerraViewerHowitzer: {
- DisplayName: Terra Viewer Howitzer
+ DisplayName:泰拉观察者
Tooltip: ""
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Weapons.Summon.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Weapons.Summon.hjson
index 89b46d4a5..958a9a2e9 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Weapons.Summon.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.Items.Weapons.Summon.hjson
@@ -13,86 +13,98 @@ AuburnBell: {
}
GrilledSquidTentacle: {
- DisplayName: Grilled Squid Tentacle
+ DisplayName: 烤鱿鱼须
Tooltip: ""
}
ToothStaff: {
- DisplayName: Tooth Staff
- Tooltip: ""
+ DisplayName: ç 牙å¬å”¤æ–
+ Tooltip: "å¬å”¤ç ç‰™ä¸ºä½ è€Œæˆ˜"
}
DarknessFan: {
- DisplayName: Darkness Fan
- Tooltip: ""
+ DisplayName: å¹»è¶è¤ç«æ‰‡
+ Tooltip:
+ '''
+ å³é”®å¯ä»¥è¿œç¨‹æ”»å‡»
+ æ ‡è®°æœ€åŽä¸€ä¸ªè¢«å‡»ä¸çš„æ•Œäºº
+ '''
}
EvilChrysalis: {
- DisplayName: Evil Chrysalis
- Tooltip: ""
+ DisplayName: 邪茧åµåŒ–æ–
+ Tooltip: "å¬å”¤å°é£žè›¾ä½œæˆ˜"
}
XmasWhip: {
- DisplayName: Xmas Whip
+ DisplayName: åœ£è¯žæ ‘éž
Tooltip: ""
}
ActivatedJellyGland: {
- DisplayName: Activated Jelly Gland
- Tooltip: ""
+ DisplayName: 活化çƒå†»è…ºä½“
+ Tooltip: "å¬å”¤çƒå†»ä½œæˆ˜"
}
MeltingSideGyroscope: {
- DisplayName: Melting Side Gyroscope
+ DisplayName: 熔边陀螺
Tooltip: ""
}
MidwinterNightmare: {
- DisplayName: Midwinter Nightmare
- Tooltip: ""
+ DisplayName: ç²¾çµæç¯
+ Tooltip:
+ '''
+ 哨兵,在地上å¬å”¤ä¸€å°¾éƒ¨æŒ‚有ç¯ç¬¼çš„çŸ®æ ‘ï¼Œå½“æ•Œæ€ªé 近时,本体从地下伸出
+ 有100%的近战伤害,20å¸§é—´éš”ï¼›åŒæ—¶æœ¬ä½“å‘射高速但çŸè·å¼¹å¹•æ”»å‡»æ•Œæ€ªï¼Œé€ æˆ100%伤害,20帧间隔
+ '''
}
ThermoprobeStaff: {
- DisplayName: Thermoprobe Staff
- Tooltip: ""
+ DisplayName: çƒæŽ¢å•å…ƒæ–
+ Tooltip:
+ '''
+ å¬å”¤1个浮游å•元,浮游å•元会对敌人å‘出ç«çƒã€‚æ¯ä¸ªæµ®æ¸¸å•元装有3å‘å¼¹è¯ï¼Œæ‰“完销æ¯
+ 最多拥有两å€å¬å”¤ä¸Šé™ä¸ªæµ®æ¸¸å•å…ƒ
+ '''
}
WiltedForestLamp: {
- DisplayName: Wilted Forest Lamp
- Tooltip: ""
+ DisplayName: 凋零森ç¯
+ Tooltip: "å¬å”¤èƒ½å‘射追踪法术的森ç¯ï¼Œé‡Šæ”¾ä¸€å®šæ³•术åŽä¼šè‡ªçˆ†é€ æˆèŒƒå›´å‡‹äº¡æŸä¼¤"
}
YggdrasilStoneGyroscope: {
- DisplayName: Yggdrasil Stone Gyroscope
+ DisplayName: 天穹岩陀螺
Tooltip: ""
}
DeadBeetleEgg: {
- DisplayName: Dead Beetle Egg
+ DisplayName: æ»ç”²è™«åµ
Tooltip: ""
}
EvilMusicRemnant: {
- DisplayName: Evil Music Remnant
+ DisplayName: é”律残ç«
Tooltip: ""
}
LegumeGyroscope: {
- DisplayName: Legume Gyroscope
+ DisplayName: 裂èšé™€èžº
Tooltip: ""
}
WoodlandWraithStaff: {
- DisplayName: Woodland Wraith Staff
+ DisplayName: æ£®å®‡å¹½é‚æ³•æ–
Tooltip: ""
}
LichenTentacle: {
- DisplayName: Lichen Tentacle
+ DisplayName: 真èŒè§¦æ‰‹
Tooltip: ""
}
DevilHeartGyroscope: {
- DisplayName: Devil Heart Gyroscope
+ DisplayName: é”心陀螺
Tooltip: ""
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.NPCs.TownNPCs.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.NPCs.TownNPCs.hjson
index aa8604424..56d28ee91 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.NPCs.TownNPCs.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.NPCs.TownNPCs.hjson
@@ -1,5 +1,5 @@
CanteenMaid: {
- DisplayName: Betty, the Canteen Maid
+ DisplayName: é¤åޅ女仆è´è’‚
TownNPCMood: {
Content: I feel pretty fine right now.
@@ -22,25 +22,25 @@ CanteenMaid: {
}
Fevens: {
- DisplayName: Fevens
+ DisplayName: éœæ–‡å£«
}
Guard_of_YggdrasilTown: {
- DisplayName: Guard_of_ Yggdrasil Town
+ DisplayName: 天穹引路人
}
Howard_Warden: {
- DisplayName: Howard_ Warden
+ DisplayName: è¦é•¿éœåŽå¾·
}
InnKeeper: {
- DisplayName: Inn Keeper
+ DisplayName: é…’é¦†è€æ¿æ ¼å°”æ ¼
}
Restauranteur: {
- DisplayName: Restauranteur
+ DisplayName: é¤åŽ…è€æ¿ç½—å°”
}
TeahouseLady: {
- DisplayName: Teahouse Lady
+ DisplayName: èŒ¶é¦†è€æ¿å¨˜å¤œç’ƒ
}
diff --git a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.NPCs.hjson b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.NPCs.hjson
index 939086613..d8c1f94b4 100644
--- a/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.NPCs.hjson
+++ b/Sources/Everglow/Localization/zh-Hans/Mods.Everglow.NPCs.hjson
@@ -19,209 +19,209 @@ ShadowstrikeCaterpillart.DisplayName: Arboreal Caterpillar
WhisperingGhost.DisplayName: Whispering Ghost
RapierMaster_Boss: {
- DisplayName: Rapier Master_ Boss
+ DisplayName: 刺剑大师
}
InfoRegisteryTestNPC: {
- DisplayName: Info Registery TestNPC
+ DisplayName: 测试NPCéžæ¨¡ç»„内容
}
BloodTusk: {
- DisplayName: Blood Tusk
+ DisplayName: 鲜血ç 牙
}
Living_Jawbone: {
- DisplayName: Living_ Jawbone
+ DisplayName: 活颌骨
}
GlowingHeal: {
- DisplayName: Glowing Heal
+ DisplayName: 治愈性æµå…‰
}
BlackStarFruit: {
- DisplayName: Black Star Fruit
+ DisplayName: è¤ç¯æžœ
}
CentipedeHead: {
- DisplayName: Centipede Head
+ DisplayName: æµè¤èœˆèš£
}
CentipedeBody: {
- DisplayName: Centipede Body
+ DisplayName: æµè¤èœˆèš£
}
CentipedeTail: {
- DisplayName: Centipede Tail
+ DisplayName: æµè¤èœˆèš£
}
Dendroid_normal: {
- DisplayName: Dendroid_normal
+ DisplayName: æµè¤æž¯æœ¨äºº
}
FireflyPiranha: {
- DisplayName: Firefly Piranha
+ DisplayName: æµè¤è™Žé±¼
}
FireflyPiranhaInfected: {
- DisplayName: Firefly Piranha Infected
+ DisplayName: 感染æµè¤è™Žé±¼
}
FireflyPiranhaInfected_small: {
- DisplayName: Firefly Piranha Infected_small
+ DisplayName: 感染æµè¤è™Žé±¼
}
FireflyPiranha_small: {
- DisplayName: Firefly Piranha_small
+ DisplayName: æµè¤è™Žé±¼
}
GlowingFirefly: {
- DisplayName: Glowing Firefly
+ DisplayName: æµè¤è¤ç«è™«
}
LittleFireBulb: {
- DisplayName: Little Fire Bulb
+ DisplayName: å°ç«æ»´
}
CorruptMoth: {
- DisplayName: Corrupt Moth
+ DisplayName: è…æª€å·¨è›¾
}
EvilPack: {
- DisplayName: Evil Pack
+ DisplayName: 巨大夜光茧
}
SummonedButterfly: {
- DisplayName: Summoned Butterfly
+ DisplayName: 幻影蛾
}
ExplosiveLantern_growing: {
- DisplayName: Explosive Lantern_growing
+ DisplayName: çˆ†ç ´ç¯ç¬¼
}
BloodLanternGhost: {
- DisplayName: Blood Lantern Ghost
+ DisplayName: 血色ç¯ç¬¼
}
BombLantern: {
- DisplayName: Bomb Lantern
+ DisplayName: 炸弹ç¯ç¬¼
}
CylindricalLantern: {
- DisplayName: Cylindrical Lantern
+ DisplayName: ç«æŸ±ç¯ç¬¼
}
FloatLantern: {
- DisplayName: Float Lantern
+ DisplayName: 鬼ç¯ç¬¼
}
RedPackBomber: {
- DisplayName: Red Pack Bomber
+ DisplayName: 红包轰炸机
}
LanternGhostKing: {
- DisplayName: Lantern Ghost King
+ DisplayName: ç¯ç¬¼é¬¼çŽ‹
}
BlueCore: {
- DisplayName: Blue Core
+ DisplayName: è“æ ¸å¿ƒ
}
FlamingDashCore: {
- DisplayName: Flaming Dash Core
+ DisplayName: ä¸ç的花ç«å¹»é‚心
}
GreenCore: {
- DisplayName: Green Core
+ DisplayName: ç»¿æ ¸å¿ƒ
}
RedCore: {
- DisplayName: Red Core
+ DisplayName: çº¢æ ¸å¿ƒ
}
YellowCore: {
- DisplayName: Yellow Core
+ DisplayName: é»„æ ¸å¿ƒ
}
Acytaea: {
- DisplayName: Acytaea
+ DisplayName: 雅斯塔亚
}
Acytaea_Boss: {
- DisplayName: Acytaea_ Boss
+ DisplayName: 雅斯塔亚
}
BarkSpicyCaterpillar: {
- DisplayName: Bark Spicy Caterpillar
+ DisplayName: æ ‘çš®åˆºæ¯›è™«
}
BrownCaterpillar: {
- DisplayName: Brown Caterpillar
+ DisplayName: 棕色毛虫
}
CarapaceCaterpillar: {
- DisplayName: Carapace Caterpillar
+ DisplayName: 石甲壳毛虫
}
CrimsonSpell: {
- DisplayName: Crimson Spell
+ DisplayName: 血月教徒
}
CyanOreBeetle: {
- DisplayName: Cyan Ore Beetle
+ DisplayName: é’缎甲虫
}
DarkGlimmeringRods: {
- DisplayName: Dark Glimmering Rods
+ DisplayName: 金棕飞æ£
}
Guard_Slimy: {
- DisplayName: Guard_ Slimy
+ DisplayName: å°å²
}
JellyBall: {
- DisplayName: Jelly Ball
+ DisplayName: çƒå†»
}
LampFruitBorer: {
- DisplayName: Lamp Fruit Borer
+ DisplayName: ç¯æžœèžŸ
}
LeafcutterAnt: {
- DisplayName: Leafcutter Ant
+ DisplayName: 切å¶èš
}
LightBulb: {
- DisplayName: Light Bulb
+ DisplayName: ç¯æ³¡èŠ±è‹ž
}
RockElemental: {
- DisplayName: Rock Elemental
+ DisplayName: ç£çŸ³å…ƒç´
}
ShadowstrikeCaterpillar: {
- DisplayName: Shadowstrike Caterpillar
+ DisplayName: 夜行毛虫
}
WhisperingGhost: {
- DisplayName: Whispering Ghost
+ DisplayName: 低è¯å¹½çµ
}
Acytaea_yggdrasil: {
- DisplayName: Acytaea_yggdrasil
+ DisplayName: 雅斯塔亚
}
SquamousShell: {
- DisplayName: Squamous Shell
+ DisplayName: 龙鳞å¤å£³
}
KingJellyBall: {
- DisplayName: King Jelly Ball
+ DisplayName: çƒå†»çŽ‹
}
RiverSlug: {
- DisplayName: River Slug
+ DisplayName: 水蛞è“
}
TestNPC: {
- DisplayName: TestNPC
+ DisplayName: 测试NPC
}
diff --git a/Sources/Everglow/build.txt b/Sources/Everglow/build.txt
index a2f5b4fc1..9bbb415c5 100644
--- a/Sources/Everglow/build.txt
+++ b/Sources/Everglow/build.txt
@@ -1,4 +1,4 @@
displayName = Everglow | æµå…‰æ— é™… [Demonstration]
author = Dream Chaser Group | å¤èˆŸé€æ¢¦å›¢é˜Ÿ
version = 0.2
-modReferences = SubworldLibrary
+modReferences = SubworldLibrary,ModLiquidLib
diff --git a/Sources/Modules/CagedDomain/Dusts/SluiceWallLamp_dust.cs b/Sources/Modules/CagedDomain/Dusts/SluiceWallLamp_dust.cs
new file mode 100644
index 000000000..764e22b97
--- /dev/null
+++ b/Sources/Modules/CagedDomain/Dusts/SluiceWallLamp_dust.cs
@@ -0,0 +1,5 @@
+namespace Everglow.CagedDomain.Dusts;
+
+public class SluiceWallLamp_dust : ModDust
+{
+}
diff --git a/Sources/Modules/CagedDomain/Dusts/SluiceWallLamp_dust.png b/Sources/Modules/CagedDomain/Dusts/SluiceWallLamp_dust.png
new file mode 100644
index 000000000..be1146d49
Binary files /dev/null and b/Sources/Modules/CagedDomain/Dusts/SluiceWallLamp_dust.png differ
diff --git a/Sources/Modules/CagedDomain/Items/BarrierBlock_Item.cs b/Sources/Modules/CagedDomain/Items/BarrierBlock_Item.cs
new file mode 100644
index 000000000..0d12f3002
--- /dev/null
+++ b/Sources/Modules/CagedDomain/Items/BarrierBlock_Item.cs
@@ -0,0 +1,15 @@
+using Everglow.CagedDomain.Tiles;
+
+namespace Everglow.CagedDomain.Items;
+
+public class BarrierBlock_Item : ModItem
+{
+ public override string LocalizationCategory => Commons.Utilities.LocalizationUtils.Categories.Placeables;
+
+ public override void SetDefaults()
+ {
+ Item.DefaultToPlaceableTile(ModContent.TileType());
+ Item.useTime = 5;
+ Item.useAnimation = 5;
+ }
+}
diff --git a/Sources/Modules/CagedDomain/Items/BarrierBlock_Item.png b/Sources/Modules/CagedDomain/Items/BarrierBlock_Item.png
new file mode 100644
index 000000000..b48159968
Binary files /dev/null and b/Sources/Modules/CagedDomain/Items/BarrierBlock_Item.png differ
diff --git a/Sources/Modules/CagedDomain/Items/BarrierPlatform_Item.cs b/Sources/Modules/CagedDomain/Items/BarrierPlatform_Item.cs
new file mode 100644
index 000000000..891b95e26
--- /dev/null
+++ b/Sources/Modules/CagedDomain/Items/BarrierPlatform_Item.cs
@@ -0,0 +1,30 @@
+using Everglow.CagedDomain.Tiles;
+using Terraria.GameContent.Creative;
+
+namespace Everglow.CagedDomain.Items;
+
+public class BarrierPlatform_Item : ModItem
+{
+ public override string LocalizationCategory => Commons.Utilities.LocalizationUtils.Categories.Placeables;
+
+ public override void SetStaticDefaults()
+ {
+ CreativeItemSacrificesCatalog.Instance.SacrificeCountNeededByItemId[Type] = 200;
+ }
+
+ public override void SetDefaults()
+ {
+ Item.DefaultToPlaceableTile(ModContent.TileType());
+ Item.width = 24;
+ Item.height = 18;
+ Item.useTime = 5;
+ Item.useAnimation = 5;
+ }
+
+ public override void AddRecipes()
+ {
+ Recipe recipe = CreateRecipe(2);
+ recipe.AddIngredient(ModContent.ItemType(), 1);
+ recipe.Register();
+ }
+}
diff --git a/Sources/Modules/CagedDomain/Items/BarrierPlatform_Item.png b/Sources/Modules/CagedDomain/Items/BarrierPlatform_Item.png
new file mode 100644
index 000000000..38d840f9c
Binary files /dev/null and b/Sources/Modules/CagedDomain/Items/BarrierPlatform_Item.png differ
diff --git a/Sources/Modules/CagedDomain/Items/MorphoFrame_Item.cs b/Sources/Modules/CagedDomain/Items/MorphoFrame_Item.cs
new file mode 100644
index 000000000..732797b84
--- /dev/null
+++ b/Sources/Modules/CagedDomain/Items/MorphoFrame_Item.cs
@@ -0,0 +1,15 @@
+using Everglow.CagedDomain.Tiles.OnWallTiles;
+
+namespace Everglow.CagedDomain.Items;
+
+public class MorphoFrame_Item : ModItem
+{
+ public override string LocalizationCategory => Everglow.Commons.Utilities.LocalizationUtils.Categories.Placeables;
+
+ public override void SetDefaults()
+ {
+ Item.DefaultToPlaceableTile(ModContent.TileType());
+ Item.width = 26;
+ Item.height = 26;
+ }
+}
diff --git a/Sources/Modules/CagedDomain/Items/MorphoFrame_Item.png b/Sources/Modules/CagedDomain/Items/MorphoFrame_Item.png
new file mode 100644
index 000000000..fd5d48ac7
Binary files /dev/null and b/Sources/Modules/CagedDomain/Items/MorphoFrame_Item.png differ
diff --git a/Sources/Modules/CagedDomain/Items/NormalEscalator_Item.cs b/Sources/Modules/CagedDomain/Items/NormalEscalator_Item.cs
new file mode 100644
index 000000000..fef83fbab
--- /dev/null
+++ b/Sources/Modules/CagedDomain/Items/NormalEscalator_Item.cs
@@ -0,0 +1,43 @@
+using Everglow.CagedDomain.Tiles.Escalator;
+using Terraria.GameInput;
+
+namespace Everglow.CagedDomain.Items;
+
+public class NormalEscalator_Item : ModItem
+{
+ public override string LocalizationCategory => Everglow.Commons.Utilities.LocalizationUtils.Categories.Placeables;
+
+ public int PlaceState = 0;
+
+ public override void SetDefaults()
+ {
+ Item.DefaultToPlaceableTile(ModContent.TileType());
+ Item.width = 40;
+ Item.height = 34;
+ Item.value = 40000;
+ }
+
+ public override void HoldItem(Player player)
+ {
+ if (PlayerInput.Triggers.JustReleased.MouseRight)
+ {
+ PlaceState = (PlaceState + 1) % 2;
+ }
+ switch (PlaceState)
+ {
+ case 0:
+ Item.DefaultToPlaceableTile(ModContent.TileType());
+ Item.width = 40;
+ Item.height = 34;
+ Item.value = 40000;
+ break;
+ case 1:
+ Item.DefaultToPlaceableTile(ModContent.TileType());
+ Item.width = 40;
+ Item.height = 34;
+ Item.value = 40000;
+ break;
+ }
+ Item.placeStyle = Math.Max(-player.direction, 0);
+ }
+}
diff --git a/Sources/Modules/CagedDomain/Items/NormalEscalator_Item.png b/Sources/Modules/CagedDomain/Items/NormalEscalator_Item.png
new file mode 100644
index 000000000..ef523278e
Binary files /dev/null and b/Sources/Modules/CagedDomain/Items/NormalEscalator_Item.png differ
diff --git a/Sources/Modules/CagedDomain/Items/PierWithSlabsTop_Item.cs b/Sources/Modules/CagedDomain/Items/PierWithSlabsTop_Item.cs
new file mode 100644
index 000000000..fa715a130
--- /dev/null
+++ b/Sources/Modules/CagedDomain/Items/PierWithSlabsTop_Item.cs
@@ -0,0 +1,38 @@
+using Everglow.CagedDomain.Tiles;
+
+namespace Everglow.CagedDomain.Items;
+
+public class PierWithSlabsTop_Item : ModItem
+{
+ public override string LocalizationCategory => Everglow.Commons.Utilities.LocalizationUtils.Categories.Placeables;
+
+ public override void SetDefaults()
+ {
+ Item.DefaultToPlaceableTile(ModContent.TileType());
+ Item.width = 50;
+ Item.height = 34;
+ Item.value = 20000;
+ }
+
+ public override void HoldItem(Player player)
+ {
+ Main.placementPreview = true;
+ }
+
+ public override bool CanUseItem(Player player)
+ {
+ var pWST = TileLoader.GetTile(ModContent.TileType()) as PierWithSlabsTop;
+ if (pWST != null)
+ {
+ int x = (int)(Main.MouseWorld.X / 16);
+ int y = (int)(Main.MouseWorld.Y / 16);
+ if (pWST.NoCollideInSolidGrid(x, y, false))
+ {
+ pWST.PlaceAtTileObjectDataOrigin(x, y);
+ Item.stack--;
+ return false;
+ }
+ }
+ return false;
+ }
+}
diff --git a/Sources/Modules/CagedDomain/Items/PierWithSlabsTop.png b/Sources/Modules/CagedDomain/Items/PierWithSlabsTop_Item.png
similarity index 100%
rename from Sources/Modules/CagedDomain/Items/PierWithSlabsTop.png
rename to Sources/Modules/CagedDomain/Items/PierWithSlabsTop_Item.png
diff --git a/Sources/Modules/CagedDomain/Items/PierWithSlabsTop.cs b/Sources/Modules/CagedDomain/Items/SluiceWallLamp_Item.cs
similarity index 53%
rename from Sources/Modules/CagedDomain/Items/PierWithSlabsTop.cs
rename to Sources/Modules/CagedDomain/Items/SluiceWallLamp_Item.cs
index 6a7a8204d..b09e0f221 100644
--- a/Sources/Modules/CagedDomain/Items/PierWithSlabsTop.cs
+++ b/Sources/Modules/CagedDomain/Items/SluiceWallLamp_Item.cs
@@ -1,14 +1,14 @@
namespace Everglow.CagedDomain.Items;
-public class PierWithSlabsTop : ModItem
+public class SluiceWallLamp_Item : ModItem
{
public override string LocalizationCategory => Everglow.Commons.Utilities.LocalizationUtils.Categories.Placeables;
public override void SetDefaults()
{
- Item.DefaultToPlaceableTile(ModContent.TileType());
- Item.width = 50;
- Item.height = 34;
- Item.value = 7086;
+ Item.DefaultToPlaceableTile(ModContent.TileType());
+ Item.width = 24;
+ Item.height = 18;
+ Item.value = 1000;
}
}
diff --git a/Sources/Modules/CagedDomain/Items/SluiceWallLamp_Item.png b/Sources/Modules/CagedDomain/Items/SluiceWallLamp_Item.png
new file mode 100644
index 000000000..de6be4057
Binary files /dev/null and b/Sources/Modules/CagedDomain/Items/SluiceWallLamp_Item.png differ
diff --git a/Sources/Modules/CagedDomain/Items/WhiteCallaLily_Item.cs b/Sources/Modules/CagedDomain/Items/WhiteCallaLily_Item.cs
index c520215c7..7a3100ba4 100644
--- a/Sources/Modules/CagedDomain/Items/WhiteCallaLily_Item.cs
+++ b/Sources/Modules/CagedDomain/Items/WhiteCallaLily_Item.cs
@@ -13,11 +13,6 @@ public override void SetDefaults()
Item.height = 48;
}
- public override bool? UseItem(Player player)
- {
- return base.UseItem(player);
- }
-
public override void HoldItem(Player player)
{
Item.placeStyle = Math.Max(player.direction, 0);
diff --git a/Sources/Modules/CagedDomain/Items/WhiteCallaLily_Item.png b/Sources/Modules/CagedDomain/Items/WhiteCallaLily_Item.png
index 17e5c656c..34e6da3bc 100644
Binary files a/Sources/Modules/CagedDomain/Items/WhiteCallaLily_Item.png and b/Sources/Modules/CagedDomain/Items/WhiteCallaLily_Item.png differ
diff --git a/Sources/Modules/CagedDomain/Tiles/BarrierBlock.cs b/Sources/Modules/CagedDomain/Tiles/BarrierBlock.cs
new file mode 100644
index 000000000..14f11fc5a
--- /dev/null
+++ b/Sources/Modules/CagedDomain/Tiles/BarrierBlock.cs
@@ -0,0 +1,87 @@
+using Everglow.CagedDomain.Items;
+
+namespace Everglow.CagedDomain.Tiles;
+
+public class BarrierBlock : ModTile
+{
+ public override void SetStaticDefaults()
+ {
+ Main.tileSolid[Type] = true;
+ Main.tileMergeDirt[Type] = true;
+ Main.tileBlockLight[Type] = false;
+ AddMapEntry(Color.Transparent);
+ MinPick = int.MaxValue;
+ }
+
+ public override void PlaceInWorld(int i, int j, Item item)
+ {
+ var tile = Main.tile[i, j];
+ tile.IsTileInvisible = true;
+ }
+
+ public override void NumDust(int i, int j, bool fail, ref int num) => num = 0;
+
+ public override bool CanKillTile(int i, int j, ref bool blockDamaged) => false;
+
+ public override bool CanExplode(int i, int j) => false;
+
+ public override bool TileFrame(int i, int j, ref bool resetFrame, ref bool noBreak)
+ {
+ noBreak = true;
+ return base.TileFrame(i, j, ref resetFrame, ref noBreak);
+ }
+
+ public override bool PreDraw(int i, int j, SpriteBatch spriteBatch)
+ {
+ if (PlayerHeldBarrierItem(Main.LocalPlayer))
+ {
+ var tile = Main.tile[i, j];
+ Vector2 zero = new Vector2(Main.offScreenRange, Main.offScreenRange);
+ if (Main.drawToScreen)
+ {
+ zero = Vector2.Zero;
+ }
+ var frame = new Rectangle(tile.TileFrameX, tile.TileFrameY, 16, 16);
+ Texture2D tex = Commons.ModAsset.HalfTiles.Value;
+ var drawColor = new Color(1f, 0, 0, 0);
+ int count = 10;
+ if (tile.Slope == SlopeType.SlopeDownLeft)
+ {
+ frame = new Rectangle(36, 0, 16, 16);
+ }
+ if (tile.Slope == SlopeType.SlopeDownRight)
+ {
+ frame = new Rectangle(54, 0, 16, 16);
+ }
+ if (tile.Slope == SlopeType.SlopeUpLeft)
+ {
+ frame = new Rectangle(90, 0, 16, 16);
+ }
+ if (tile.Slope == SlopeType.SlopeUpRight)
+ {
+ frame = new Rectangle(72, 0, 16, 16);
+ }
+ if (tile.IsHalfBlock)
+ {
+ frame = new Rectangle(18, 0, 16, 16);
+ }
+ if (tile.Slope == SlopeType.Solid && !tile.IsHalfBlock)
+ {
+ tex = ModAsset.BarrierBlock_Visable.Value;
+ drawColor = Color.White;
+ count = 1;
+ }
+ for (int k = 0; k < count; k++)
+ {
+ spriteBatch.Draw(tex, new Vector2(i, j) * 16 - Main.screenPosition + zero, frame, drawColor, 0, new Vector2(0), 1f, SpriteEffects.None, 0);
+ }
+ }
+ return base.PreDraw(i, j, spriteBatch);
+ }
+
+ public static bool PlayerHeldBarrierItem(Player player)
+ {
+ // return true;
+ return player.HeldItem.type == ModContent.ItemType() || player.HeldItem.type == ModContent.ItemType() || player.HeldItem.hammer > 0 | player.HeldItem.pick > 0;
+ }
+}
diff --git a/Sources/Modules/CagedDomain/Tiles/BarrierBlock.png b/Sources/Modules/CagedDomain/Tiles/BarrierBlock.png
new file mode 100644
index 000000000..e8ffd1d5a
Binary files /dev/null and b/Sources/Modules/CagedDomain/Tiles/BarrierBlock.png differ
diff --git a/Sources/Modules/CagedDomain/Tiles/BarrierBlock_Visable.png b/Sources/Modules/CagedDomain/Tiles/BarrierBlock_Visable.png
new file mode 100644
index 000000000..1717e2d17
Binary files /dev/null and b/Sources/Modules/CagedDomain/Tiles/BarrierBlock_Visable.png differ
diff --git a/Sources/Modules/CagedDomain/Tiles/BarrierPlatform.cs b/Sources/Modules/CagedDomain/Tiles/BarrierPlatform.cs
new file mode 100644
index 000000000..6775e354d
--- /dev/null
+++ b/Sources/Modules/CagedDomain/Tiles/BarrierPlatform.cs
@@ -0,0 +1,73 @@
+using Terraria.ObjectData;
+
+namespace Everglow.CagedDomain.Tiles;
+
+public class BarrierPlatform : ModTile
+{
+ public override void SetStaticDefaults()
+ {
+ // Properties
+ Main.tileLighted[Type] = true;
+ Main.tileFrameImportant[Type] = true;
+ Main.tileSolidTop[Type] = true;
+ Main.tileSolid[Type] = true;
+ Main.tileNoAttach[Type] = true;
+ Main.tileTable[Type] = true;
+ Main.tileLavaDeath[Type] = true;
+ TileID.Sets.Platforms[Type] = true;
+ TileID.Sets.DisableSmartCursor[Type] = true;
+
+ AddToArray(ref TileID.Sets.RoomNeeds.CountsAsDoor);
+ AddMapEntry(Color.Transparent);
+ AdjTiles = new int[] { TileID.Platforms };
+
+ // Placement
+ TileObjectData.newTile.CoordinateHeights = new[] { 16 };
+ TileObjectData.newTile.CoordinateWidth = 16;
+ TileObjectData.newTile.CoordinatePadding = 2;
+ TileObjectData.newTile.StyleHorizontal = true;
+ TileObjectData.newTile.StyleMultiplier = 27;
+ TileObjectData.newTile.StyleWrapLimit = 27;
+ TileObjectData.newTile.UsesCustomCanPlace = false;
+ TileObjectData.newTile.LavaDeath = true;
+ TileObjectData.addTile(Type);
+ MinPick = int.MaxValue;
+ }
+
+ public override void PlaceInWorld(int i, int j, Item item)
+ {
+ var tile = Main.tile[i, j];
+ tile.IsTileInvisible = true;
+ }
+
+ public override void PostSetDefaults() => Main.tileNoSunLight[Type] = false;
+
+ public override void NumDust(int i, int j, bool fail, ref int num) => num = 0;
+
+ public override bool CanKillTile(int i, int j, ref bool blockDamaged) => false;
+
+ public override bool CanExplode(int i, int j) => false;
+
+ public override bool TileFrame(int i, int j, ref bool resetFrame, ref bool noBreak)
+ {
+ noBreak = true;
+ return base.TileFrame(i, j, ref resetFrame, ref noBreak);
+ }
+
+ public override bool PreDraw(int i, int j, SpriteBatch spriteBatch)
+ {
+ if (BarrierBlock.PlayerHeldBarrierItem(Main.LocalPlayer))
+ {
+ var tile = Main.tile[i, j];
+ tile.IsTileInvisible = true;
+ Vector2 zero = new Vector2(Main.offScreenRange, Main.offScreenRange);
+ if (Main.drawToScreen)
+ {
+ zero = Vector2.Zero;
+ }
+ var frame = new Rectangle(tile.TileFrameX, tile.TileFrameY, 16, 16);
+ spriteBatch.Draw(ModAsset.BarrierPlatform_Visable.Value, new Vector2(i, j) * 16 - Main.screenPosition + zero, frame, Color.White, 0, new Vector2(0), 1f, SpriteEffects.None, 0);
+ }
+ return base.PreDraw(i, j, spriteBatch);
+ }
+}
diff --git a/Sources/Modules/CagedDomain/Tiles/BarrierPlatform.png b/Sources/Modules/CagedDomain/Tiles/BarrierPlatform.png
new file mode 100644
index 000000000..c2dc91e58
Binary files /dev/null and b/Sources/Modules/CagedDomain/Tiles/BarrierPlatform.png differ
diff --git a/Sources/Modules/CagedDomain/Tiles/BarrierPlatform_Highlight.png b/Sources/Modules/CagedDomain/Tiles/BarrierPlatform_Highlight.png
new file mode 100644
index 000000000..682fafa7f
Binary files /dev/null and b/Sources/Modules/CagedDomain/Tiles/BarrierPlatform_Highlight.png differ
diff --git a/Sources/Modules/CagedDomain/Tiles/BarrierPlatform_Visable.png b/Sources/Modules/CagedDomain/Tiles/BarrierPlatform_Visable.png
new file mode 100644
index 000000000..d72d771c7
Binary files /dev/null and b/Sources/Modules/CagedDomain/Tiles/BarrierPlatform_Visable.png differ
diff --git a/Sources/Modules/CagedDomain/Tiles/Escalator/NormalEscalator.cs b/Sources/Modules/CagedDomain/Tiles/Escalator/NormalEscalator.cs
new file mode 100644
index 000000000..40fee92a9
--- /dev/null
+++ b/Sources/Modules/CagedDomain/Tiles/Escalator/NormalEscalator.cs
@@ -0,0 +1,76 @@
+using Everglow.CagedDomain.Items;
+using Everglow.Commons.VFX.Scene;
+using Terraria;
+using Terraria.DataStructures;
+using Terraria.Enums;
+using Terraria.ObjectData;
+
+namespace Everglow.CagedDomain.Tiles.Escalator;
+
+public class NormalEscalator : ModTile, ISceneTile
+{
+ public override void PostSetDefaults()
+ {
+ Main.tileSolid[Type] = true;
+ Main.tileLavaDeath[Type] = true;
+ Main.tileFrameImportant[Type] = true;
+ TileObjectData.newTile.CopyFrom(TileObjectData.Style1x1);
+ TileObjectData.newTile.AnchorBottom = new AnchorData(AnchorType.None, 0, 0);
+ TileObjectData.newTile.StyleHorizontal = true;
+ TileObjectData.addTile(Type);
+ DustType = DustID.WoodFurniture;
+ AddMapEntry(new Color(153, 152, 151));
+ HitSound = SoundID.DD2_SkeletonHurt;
+ }
+
+ public override void NumDust(int i, int j, bool fail, ref int num)
+ {
+ num = 0;
+ base.NumDust(i, j, fail, ref num);
+ }
+
+ public void AddScene(int i, int j)
+ {
+ int dir = 1;
+ Tile tile = Main.tile[i, j];
+ if (tile.TileFrameX == 18)
+ {
+ dir = -1;
+ }
+ var escalator_VFX = new NormalEscalator_VFX()
+ {
+ OriginTilePos = new Point(i, j),
+ OriginTileType = Type,
+ Position = new Vector2(i * 16, j * 16),
+ Direction = dir,
+ State = tile.TileFrameY / 18,
+ Active = true,
+ Visible = true,
+ };
+ Ins.VFXManager.Add(escalator_VFX);
+ }
+
+ public override void PostDraw(int i, int j, SpriteBatch spriteBatch)
+ {
+ Player player = Main.LocalPlayer;
+ if (player.HeldItem.type == ModContent.ItemType())
+ {
+ Vector2 zero = new Vector2(Main.offScreenRange);
+ if (Main.drawToScreen)
+ {
+ zero = Vector2.Zero;
+ }
+ Tile tile = Main.tile[i, j];
+ int dir = 1;
+ if (tile.TileFrameX == 18)
+ {
+ dir = -1;
+ }
+ Texture2D tex = Commons.ModAsset.TileBlock.Value;
+ for (int k = 1; k < 120; k++)
+ {
+ spriteBatch.Draw(tex, new Vector2(i + k * dir, j - k) * 16 - Main.screenPosition + zero, null, new Color(0f, 1f, 0f, 0f), 0, Vector2.zeroVector, 1f, SpriteEffects.None, 0);
+ }
+ }
+ }
+}
diff --git a/Sources/Modules/CagedDomain/Tiles/Escalator/NormalEscalator.png b/Sources/Modules/CagedDomain/Tiles/Escalator/NormalEscalator.png
new file mode 100644
index 000000000..610a74f20
Binary files /dev/null and b/Sources/Modules/CagedDomain/Tiles/Escalator/NormalEscalator.png differ
diff --git a/Sources/Modules/CagedDomain/Tiles/Escalator/NormalEscalator_Atlas.png b/Sources/Modules/CagedDomain/Tiles/Escalator/NormalEscalator_Atlas.png
new file mode 100644
index 000000000..144e15458
Binary files /dev/null and b/Sources/Modules/CagedDomain/Tiles/Escalator/NormalEscalator_Atlas.png differ
diff --git a/Sources/Modules/CagedDomain/Tiles/Escalator/NormalEscalator_Top.cs b/Sources/Modules/CagedDomain/Tiles/Escalator/NormalEscalator_Top.cs
new file mode 100644
index 000000000..6de16be6c
--- /dev/null
+++ b/Sources/Modules/CagedDomain/Tiles/Escalator/NormalEscalator_Top.cs
@@ -0,0 +1,28 @@
+using Terraria.DataStructures;
+using Terraria.Enums;
+using Terraria.ObjectData;
+
+namespace Everglow.CagedDomain.Tiles.Escalator;
+
+public class NormalEscalator_Top : ModTile
+{
+ public override void PostSetDefaults()
+ {
+ Main.tileSolid[Type] = true;
+ Main.tileLavaDeath[Type] = true;
+ Main.tileFrameImportant[Type] = true;
+ TileObjectData.newTile.CopyFrom(TileObjectData.Style1x1);
+ TileObjectData.newTile.AnchorBottom = new AnchorData(AnchorType.None, 0, 0);
+ TileObjectData.newTile.StyleHorizontal = true;
+ TileObjectData.addTile(Type);
+ DustType = DustID.WoodFurniture;
+ AddMapEntry(new Color(153, 152, 151));
+ HitSound = SoundID.DD2_SkeletonHurt;
+ }
+
+ public override void NumDust(int i, int j, bool fail, ref int num)
+ {
+ num = 0;
+ base.NumDust(i, j, fail, ref num);
+ }
+}
diff --git a/Sources/Modules/CagedDomain/Tiles/Escalator/NormalEscalator_Top.png b/Sources/Modules/CagedDomain/Tiles/Escalator/NormalEscalator_Top.png
new file mode 100644
index 000000000..872edd9fd
Binary files /dev/null and b/Sources/Modules/CagedDomain/Tiles/Escalator/NormalEscalator_Top.png differ
diff --git a/Sources/Modules/CagedDomain/Tiles/Escalator/NormalEscalator_VFX.cs b/Sources/Modules/CagedDomain/Tiles/Escalator/NormalEscalator_VFX.cs
new file mode 100644
index 000000000..b6e702760
--- /dev/null
+++ b/Sources/Modules/CagedDomain/Tiles/Escalator/NormalEscalator_VFX.cs
@@ -0,0 +1,380 @@
+using Everglow.Commons.Enums;
+using Everglow.Commons.TileHelper;
+using Everglow.Commons.Utilities;
+using Everglow.Commons.Vertex;
+using Everglow.Commons.VFX;
+using Everglow.Commons.VFX.Pipelines;
+using Everglow.Commons.VFX.Scene;
+
+namespace Everglow.CagedDomain.Tiles.Escalator;
+
+///
+/// An interactive escalator.
+/// It connect the NormalEscalator and NormalEscalator_Top tiles by an oblique escalator.
+/// Player should control 'Up' to attach to the escalator, and 'Down' to exit the escalator.
+///
+[Pipeline(typeof(WCSPipeline))]
+public class NormalEscalator_VFX : TileVFX
+{
+ public override CodeLayer DrawLayer => CodeLayer.PostDrawPlayers;
+
+ public Rectangle HanddrailStrap_Bottom = new Rectangle(0, 0, 88, 54);
+ public Rectangle HanddrailStrap_Medium = new Rectangle(92, 0, 44, 44);
+ public Rectangle HanddrailStrap_Top = new Rectangle(140, 0, 70, 44);
+
+ public Rectangle ExteriorPanel_Bottom = new Rectangle(0, 60, 58, 16);
+ public Rectangle ExteriorPanel_Medium_Bottom = new Rectangle(136, 44, 30, 32);
+ public Rectangle ExteriorPanel_Medium = new Rectangle(80, 48, 26, 28);
+ public Rectangle ExteriorPanel_Medium_Top = new Rectangle(108, 50, 24, 24);
+ public Rectangle ExteriorPanel_Top = new Rectangle(166, 46, 44, 16);
+
+ public Rectangle SelectedInterfaceHighlight = new Rectangle(166, 64, 18, 10);
+
+ public Rectangle StepBlock = new Rectangle(60, 60, 18, 16);
+
+ public List StepPositions = new List();
+
+ public List AttachingPlayers = new List();
+
+ public int TotalLength = 0;
+
+ public float MoveingSpeed = 16f / 30f;
+
+ public float StepValue = 0;
+
+ public int State = 0;
+
+ public enum WorkState
+ {
+ Upward,
+ Downward,
+ Cease,
+ }
+
+ public override void Update()
+ {
+ if (TotalLength == 0)
+ {
+ for (int step = 0; step < 100; step++)
+ {
+ var tile = WorldGenMisc.SafeGetTile(OriginTilePos + new Point(Direction * step, -step));
+ if (tile.TileType == ModContent.TileType())
+ {
+ TotalLength = step;
+ break;
+ }
+ }
+ }
+ UpdateSteps();
+ UpdatePlayerAttachment();
+ UpdateStateControl();
+ base.Update();
+ }
+
+ public void UpdatePlayerAttachment()
+ {
+ foreach (var player in Main.player)
+ {
+ if (player is not null && player.active)
+ {
+ // TODO: Optimization, check player collide with the exterior rectangle.
+ foreach (var blockPos in StepPositions)
+ {
+ Rectangle stepBox = new Rectangle((int)blockPos.X, (int)blockPos.Y, 16, 16);
+
+ // Control 'Up';Not exist in the list;No mount;Collision;
+ if (player.controlUp && !AttachingPlayers.Contains(player) && player.mount.Type == -1 && stepBox.Intersects(player.Hitbox))
+ {
+ AttachingPlayers.Add(player);
+ break;
+ }
+ }
+ }
+ }
+
+ foreach (var player in AttachingPlayers)
+ {
+ if (player is null || !player.active)
+ {
+ AttachingPlayers.Remove(player);
+ break;
+ }
+
+ // Control 'Down' to exit the escalator..
+ if (player.controlDown)
+ {
+ AttachingPlayers.Remove(player);
+ break;
+ }
+
+ bool safe = false;
+ for (int i = 0; i < StepPositions.Count; i++)
+ {
+ Vector2 blockPos = StepPositions[i];
+ if (player.Bottom.X >= blockPos.X && player.Bottom.X < blockPos.X + 16)
+ {
+ // The speed rate constant: depends on the escalator speed (Updated by Main.time / 30f * 16)
+ // TODO: Player frame
+
+ int stateDir = 1;
+ if (State == (int)WorkState.Downward)
+ {
+ stateDir = -1;
+ }
+ if (State == (int)WorkState.Cease)
+ {
+ stateDir = 0;
+ }
+ float relativeMoveX = MoveingSpeed * Direction * stateDir;
+ if (player.Bottom.Y > blockPos.Y)
+ {
+ float deltaY = blockPos.Y - player.Bottom.Y;
+ if (MathF.Abs(deltaY) > 15)
+ {
+ player.gfxOffY -= deltaY;
+ }
+ if (MathF.Abs(player.gfxOffY) > 16)
+ {
+ player.gfxOffY = 16;
+ }
+ player.Bottom = new Vector2(player.Bottom.X + relativeMoveX, blockPos.Y);
+ if (player.bodyFrame.Y == 280)
+ {
+ player.bodyFrame.Y = 0;
+ player.legFrame.Y = 0;
+ }
+ }
+ safe = true;
+ break;
+ }
+ }
+ if (!safe)
+ {
+ AttachingPlayers.Remove(player);
+ break;
+ }
+ }
+ }
+
+ public void UpdateStateControl()
+ {
+ Rectangle controlBox = new Rectangle((int)Position.X - 1 - 35 * Direction, (int)Position.Y + 6, 18, 6);
+ if (controlBox.Contains(Main.MouseWorld.ToPoint()))
+ {
+ MouseIntersectControlInterface = true;
+ if (Main.mouseRight && Main.mouseRightRelease)
+ {
+ State++;
+ if (State > 2)
+ {
+ State = 0;
+ }
+ var tile = TileUtils.SafeGetTile(OriginTilePos);
+ tile.TileFrameY = (short)(State * 18);
+ }
+ return;
+ }
+ MouseIntersectControlInterface = false;
+ }
+
+ public bool MouseIntersectControlInterface = false;
+
+ public Rectangle CurrentAnimationPanel()
+ {
+ int animationValue = (int)(Main.time * 0.1f) % 3;
+ return new Rectangle(214, 8 * animationValue + State * 24, 18, 6);
+ }
+
+ public Rectangle CurrentAnimationPane_Glow()
+ {
+ int animationValue = (int)(Main.time * 0.1f) % 3;
+ return new Rectangle(216, 8 * animationValue + State * 24, 14, 6);
+ }
+
+ public override void Draw()
+ {
+ if (TotalLength == 0)
+ {
+ return;
+ }
+ if (Texture == null)
+ {
+ Texture = ModAsset.NormalEscalator_Atlas.Value;
+ }
+
+ // Handdrail Straps
+ Vector2 totalOffset = new Vector2(0);
+ Vector2 drawPos = Position + totalOffset;
+
+ DrawAPiece(drawPos + new Vector2(-36 - 26 * Direction, -50), HanddrailStrap_Bottom);
+ Vector2 piece_drawPos = drawPos + new Vector2(-14 - 4 * Direction, -50);
+ for (int i = 1; i < TotalLength; i++)
+ {
+ piece_drawPos += new Vector2(Direction * 16, -16);
+ DrawAPiece(piece_drawPos, HanddrailStrap_Medium);
+ }
+ if (Direction == 1)
+ {
+ DrawAPiece(drawPos + new Vector2(Direction, -1) * 16 * TotalLength + new Vector2(-18 * Direction, -42), HanddrailStrap_Top);
+ }
+ else
+ {
+ DrawAPiece(drawPos + new Vector2(Direction, -1) * 16 * TotalLength + new Vector2(-36, -42), HanddrailStrap_Top);
+ }
+
+ // Steps
+ float stepValue = StepValue % 16;
+
+ if (StepPositions != null && StepPositions.Count > 0)
+ {
+ for (int i = 0; i < StepPositions.Count; i++)
+ {
+ Rectangle stepFrame = StepBlock;
+ Vector2 offset = Vector2.zeroVector;
+ if (i == 0)
+ {
+ stepFrame = new Rectangle((int)(78 - stepValue), 60, (int)(stepValue + 2), 16);
+ if (Direction == -1)
+ {
+ offset = new Vector2(stepValue - 16, 0);
+ }
+ }
+ DrawAPiece(StepPositions[i] + offset, stepFrame);
+ }
+ }
+
+ // Exterior Panels
+ DrawAPiece(drawPos + new Vector2(-21 - 27 * Direction, 0), ExteriorPanel_Bottom);
+
+ DrawAPiece(drawPos + new Vector2(-1 - 35 * Direction, 6), CurrentAnimationPanel());
+ DrawAPieceIgnoreEnvironment(drawPos + new Vector2(1 - 35 * Direction, 6), CurrentAnimationPane_Glow(), new Color(1f, 1f, 1f, 0f));
+ if (MouseIntersectControlInterface)
+ {
+ DrawAPieceIgnoreEnvironment(drawPos + new Vector2(-1 - 35 * Direction, 4), SelectedInterfaceHighlight, new Color(1f, 1f, 1f, 1f));
+ }
+ piece_drawPos = drawPos + new Vector2(-12, -4);
+ if (Direction == -1)
+ {
+ piece_drawPos = drawPos + new Vector2(2, -4);
+ }
+ for (int i = 0; i < TotalLength; i++)
+ {
+ Vector2 offset = Vector2.zeroVector;
+ piece_drawPos += new Vector2(Direction * 16, -16);
+ Rectangle frame = ExteriorPanel_Medium;
+ if (i == 0)
+ {
+ frame = ExteriorPanel_Medium_Bottom;
+ if (Direction == 1)
+ {
+ offset = new Vector2(-4, 0);
+ }
+ else
+ {
+ offset = Vector2.zeroVector;
+ }
+ }
+ if (i == TotalLength - 1)
+ {
+ frame = ExteriorPanel_Medium_Top;
+
+ if (Direction == 1)
+ {
+ offset = new Vector2(-2, 4);
+ }
+ else
+ {
+ offset = new Vector2(4, 4);
+ }
+ }
+ DrawAPiece(piece_drawPos + offset, frame);
+ }
+
+ DrawAPiece(drawPos + new Vector2(Direction, -1) * 16 * TotalLength + new Vector2(-14 + 12 * Direction, -2), ExteriorPanel_Top);
+ }
+
+ public void DrawAPiece(Vector2 position, Rectangle frame)
+ {
+ List piece = new List();
+ if (Direction == 1)
+ {
+ piece.Add(position, Lighting.GetColor(position.ToTileCoordinates()), new Vector3(frame.TopLeft() / Texture.Size(), 0));
+ piece.Add(position + new Vector2(frame.Width, 0), Lighting.GetColor((position + new Vector2(frame.Width, 0)).ToTileCoordinates()), new Vector3(frame.TopRight() / Texture.Size(), 0));
+
+ piece.Add(position + new Vector2(0, frame.Height), Lighting.GetColor((position + new Vector2(0, frame.Height)).ToTileCoordinates()), new Vector3(frame.BottomLeft() / Texture.Size(), 0));
+ piece.Add(position + new Vector2(frame.Width, frame.Height), Lighting.GetColor((position + new Vector2(frame.Width, frame.Height)).ToTileCoordinates()), new Vector3(frame.BottomRight() / Texture.Size(), 0));
+ }
+ else
+ {
+ piece.Add(position, Lighting.GetColor(position.ToTileCoordinates()), new Vector3(frame.TopRight() / Texture.Size(), 0));
+ piece.Add(position + new Vector2(frame.Width, 0), Lighting.GetColor((position + new Vector2(frame.Width, 0)).ToTileCoordinates()), new Vector3(frame.TopLeft() / Texture.Size(), 0));
+
+ piece.Add(position + new Vector2(0, frame.Height), Lighting.GetColor((position + new Vector2(0, frame.Height)).ToTileCoordinates()), new Vector3(frame.BottomRight() / Texture.Size(), 0));
+ piece.Add(position + new Vector2(frame.Width, frame.Height), Lighting.GetColor((position + new Vector2(frame.Width, frame.Height)).ToTileCoordinates()), new Vector3(frame.BottomLeft() / Texture.Size(), 0));
+ }
+ Ins.Batch.Draw(Texture, piece, PrimitiveType.TriangleStrip);
+ }
+
+ public void DrawAPieceIgnoreEnvironment(Vector2 position, Rectangle frame, Color color)
+ {
+ List piece = new List();
+ if (Direction == 1)
+ {
+ piece.Add(position, color, new Vector3(frame.TopLeft() / Texture.Size(), 0));
+ piece.Add(position + new Vector2(frame.Width, 0), color, new Vector3(frame.TopRight() / Texture.Size(), 0));
+
+ piece.Add(position + new Vector2(0, frame.Height), color, new Vector3(frame.BottomLeft() / Texture.Size(), 0));
+ piece.Add(position + new Vector2(frame.Width, frame.Height), color, new Vector3(frame.BottomRight() / Texture.Size(), 0));
+ }
+ else
+ {
+ piece.Add(position, color, new Vector3(frame.TopRight() / Texture.Size(), 0));
+ piece.Add(position + new Vector2(frame.Width, 0), color, new Vector3(frame.TopLeft() / Texture.Size(), 0));
+
+ piece.Add(position + new Vector2(0, frame.Height), color, new Vector3(frame.BottomRight() / Texture.Size(), 0));
+ piece.Add(position + new Vector2(frame.Width, frame.Height), color, new Vector3(frame.BottomLeft() / Texture.Size(), 0));
+ }
+ Ins.Batch.Draw(Texture, piece, PrimitiveType.TriangleStrip);
+ }
+
+ public void UpdateSteps()
+ {
+ StepPositions = new List();
+ if (State == (int)WorkState.Upward)
+ {
+ StepValue += MoveingSpeed;
+ if (StepValue > 32000)
+ {
+ StepValue -= 16000;
+ }
+ }
+ else if (State == (int)WorkState.Downward)
+ {
+ StepValue -= MoveingSpeed;
+ if (StepValue < 0)
+ {
+ StepValue += 16000;
+ }
+ }
+ float stepValue = StepValue % 16;
+ Vector2 piece_drawPos = Position + new Vector2(-76 * Direction, 62) + new Vector2(Direction, -1) * stepValue;
+ for (int i = -3; i < TotalLength + 1; i++)
+ {
+ Vector2 offset = Vector2.zeroVector;
+ if (i == TotalLength)
+ {
+ offset = new Vector2(0, stepValue);
+ }
+ if (i <= -1)
+ {
+ offset = new Vector2(0, stepValue + 16 * i);
+ }
+ if (i == -3)
+ {
+ offset += new Vector2(16 - stepValue, 0);
+ }
+ piece_drawPos += new Vector2(Direction * 16, -16);
+ StepPositions.Add(piece_drawPos + offset);
+ }
+ }
+}
diff --git a/Sources/Modules/CagedDomain/Tiles/GiantBell.png b/Sources/Modules/CagedDomain/Tiles/GiantBell.png
index d1b8cdfcb..a69843afc 100644
Binary files a/Sources/Modules/CagedDomain/Tiles/GiantBell.png and b/Sources/Modules/CagedDomain/Tiles/GiantBell.png differ
diff --git a/Sources/Modules/CagedDomain/Tiles/GiantCampFire.cs b/Sources/Modules/CagedDomain/Tiles/GiantCampFire.cs
index d922b8e45..69f25eb61 100644
--- a/Sources/Modules/CagedDomain/Tiles/GiantCampFire.cs
+++ b/Sources/Modules/CagedDomain/Tiles/GiantCampFire.cs
@@ -24,7 +24,7 @@ public override void PostSetDefaults()
16,
16,
16,
- 18
+ 18,
};
TileObjectData.newTile.CoordinateWidth = 16;
TileObjectData.newTile.Origin = new Point16(2, 1);
@@ -32,16 +32,18 @@ public override void PostSetDefaults()
DustType = DustID.WoodFurniture;
AddMapEntry(new Color(91, 62, 39));
}
+
public void AddScene(int i, int j)
{
Tile tile = Main.tile[i, j];
if (tile.TileFrameX == 36 && tile.TileFrameY == 18)
{
- GiantCampFire_flame_fore flame = new GiantCampFire_flame_fore { position = new Vector2(i, j) * 16 + new Vector2(8), Active = true, Visible = true, originTile = new Point(i, j), originType = Type };
+ GiantCampFire_flame_fore flame = new GiantCampFire_flame_fore { Position = new Vector2(i, j) * 16 + new Vector2(8), Active = true, Visible = true, OriginTilePos = new Point(i, j), OriginTileType = Type };
Ins.VFXManager.Add(flame);
}
}
+
public override void NearbyEffects(int i, int j, bool closer)
{
Tile tile = Main.tile[i, j];
@@ -58,7 +60,7 @@ public override void NearbyEffects(int i, int j, bool closer)
maxTime = Main.rand.Next(37, 195),
scale = Main.rand.NextFloat(0.1f, Main.rand.NextFloat(12.1f, 27.0f)),
rotation = Main.rand.NextFloat(6.283f),
- ai = new float[] { Main.rand.NextFloat(0.0f, 0.93f), Main.rand.NextFloat(-0.003f, 0.003f) }
+ ai = new float[] { Main.rand.NextFloat(0.0f, 0.93f), Main.rand.NextFloat(-0.003f, 0.003f) },
};
Ins.VFXManager.Add(spark);
}
@@ -73,7 +75,7 @@ public override void NearbyEffects(int i, int j, bool closer)
maxTime = Main.rand.Next(37, 305),
scale = Main.rand.NextFloat(40, 100),
rotation = Main.rand.NextFloat(6.283f),
- ai = new float[] { Main.rand.NextFloat(-0.05f, -0.01f), 0 }
+ ai = new float[] { Main.rand.NextFloat(-0.05f, -0.01f), 0 },
};
Ins.VFXManager.Add(somg);
}
@@ -81,12 +83,14 @@ public override void NearbyEffects(int i, int j, bool closer)
base.NearbyEffects(i, j, closer);
}
}
+
public class GiantCampFire_flame_fore_Pipeline : Pipeline
{
public override void Load()
{
effect = ModAsset.GiantCampFire_shader;
}
+
public override void BeginRender()
{
var effect = this.effect.Value;
@@ -101,23 +105,27 @@ public override void BeginRender()
Ins.Batch.Begin(BlendState.AlphaBlend, DepthStencilState.None, SamplerState.PointWrap, RasterizerState.CullNone);
effect.CurrentTechnique.Passes[0].Apply();
}
+
public override void EndRender()
{
Ins.Batch.End();
}
}
+
[Pipeline(typeof(GiantCampFire_flame_fore_Pipeline), typeof(BloomPipeline))]
-public class GiantCampFire_flame_fore : ForegroundVFX
+public class GiantCampFire_flame_fore : TileVFX
{
public override void OnSpawn()
{
- texture = Commons.ModAsset.Noise_flame_0.Value;
+ Texture = Commons.ModAsset.Noise_flame_0.Value;
}
+
public override void Update()
{
- Lighting.AddLight(position, new Vector3(1, 0.7f, 0.2f) * 2);
+ Lighting.AddLight(Position, new Vector3(1, 0.7f, 0.2f) * 2);
base.Update();
}
+
public override void Draw()
{
float timeValue = (float)Main.time * 0.014f;
@@ -135,12 +143,12 @@ public override void Draw()
colorG = MathF.Pow(value, 0.4f);
}
float xValue = 9 * MathF.Sin(value * 32 + timeValue * 16) * value + value * value * Main.windSpeedCurrent * 870f;
- bars.Add(position + new Vector2(30 * (1 - value) + xValue, -t * 9f), new Color(colorR, colorG, value, 0f), new Vector3(0, value * 1.3f - timeValue, zValue));
- bars.Add(position + new Vector2(-30 * (1 - value) + xValue, -t * 9f), new Color(colorR, colorG, value, 0f), new Vector3(1, value * 1.3f - timeValue, zValue));
+ bars.Add(Position + new Vector2(30 * (1 - value) + xValue, -t * 9f), new Color(colorR, colorG, value, 0f), new Vector3(0, value * 1.3f - timeValue, zValue));
+ bars.Add(Position + new Vector2(-30 * (1 - value) + xValue, -t * 9f), new Color(colorR, colorG, value, 0f), new Vector3(1, value * 1.3f - timeValue, zValue));
if (t == 39)
{
- bars.Add(position + new Vector2(xValue, -t * 9f), new Color(0, colorG, 1, 0f), new Vector3(0, value * 1.3f - timeValue, zValue));
- bars.Add(position + new Vector2(xValue, -t * 9f), new Color(0, colorG, 1, 0f), new Vector3(1, value * 1.3f - timeValue, zValue));
+ bars.Add(Position + new Vector2(xValue, -t * 9f), new Color(0, colorG, 1, 0f), new Vector3(0, value * 1.3f - timeValue, zValue));
+ bars.Add(Position + new Vector2(xValue, -t * 9f), new Color(0, colorG, 1, 0f), new Vector3(1, value * 1.3f - timeValue, zValue));
}
}
for (int t = 0; t < 40; t++)
@@ -154,16 +162,16 @@ public override void Draw()
float xValue = 12 * MathF.Sin(value * 32 + timeValue * 16) * value + value * value * Main.windSpeedCurrent * 870f;
if (t == 0)
{
- bars.Add(position + new Vector2(30 * (1 - value) + xValue, -t * 12f), new Color(0, colorG, 1, 0f), new Vector3(0, value * 1.3f - timeValue, zValue));
- bars.Add(position + new Vector2(-30 * (1 - value) + xValue, -t * 12f), new Color(0, colorG, 1, 0f), new Vector3(1, value * 1.3f - timeValue, zValue));
+ bars.Add(Position + new Vector2(30 * (1 - value) + xValue, -t * 12f), new Color(0, colorG, 1, 0f), new Vector3(0, value * 1.3f - timeValue, zValue));
+ bars.Add(Position + new Vector2(-30 * (1 - value) + xValue, -t * 12f), new Color(0, colorG, 1, 0f), new Vector3(1, value * 1.3f - timeValue, zValue));
colorG = MathF.Pow(value, 0.4f);
}
- bars.Add(position + new Vector2(30 * (1 - value) + xValue, -t * 12f), new Color(colorR, colorG, value, 0f), new Vector3(0, value * 1.3f - timeValue, zValue));
- bars.Add(position + new Vector2(-30 * (1 - value) + xValue, -t * 12f), new Color(colorR, colorG, value, 0f), new Vector3(1, value * 1.3f - timeValue, zValue));
+ bars.Add(Position + new Vector2(30 * (1 - value) + xValue, -t * 12f), new Color(colorR, colorG, value, 0f), new Vector3(0, value * 1.3f - timeValue, zValue));
+ bars.Add(Position + new Vector2(-30 * (1 - value) + xValue, -t * 12f), new Color(colorR, colorG, value, 0f), new Vector3(1, value * 1.3f - timeValue, zValue));
if (t == 39)
{
- bars.Add(position + new Vector2(xValue, -t * 9f), new Color(0, 0, 1, 0f), new Vector3(0, value * 1.3f - timeValue, zValue));
- bars.Add(position + new Vector2(xValue, -t * 9f), new Color(0, 0, 1, 0f), new Vector3(1, value * 1.3f - timeValue, zValue));
+ bars.Add(Position + new Vector2(xValue, -t * 9f), new Color(0, 0, 1, 0f), new Vector3(0, value * 1.3f - timeValue, zValue));
+ bars.Add(Position + new Vector2(xValue, -t * 9f), new Color(0, 0, 1, 0f), new Vector3(1, value * 1.3f - timeValue, zValue));
}
}
for (int t = 0; t < 20; t++)
@@ -177,12 +185,12 @@ public override void Draw()
float xValue = 3 * MathF.Sin(value * 32 + timeValue * 16) * value - value * 50;
if (t == 0)
{
- bars.Add(position + new Vector2(12 * (1 - value) + xValue, t * 3.5f - 15), new Color(0, colorG, 1, 0f), new Vector3(0, value * 0.73f + timeValue * 0.75f, zValue));
- bars.Add(position + new Vector2(-25 * (1 - value) + xValue, t * 3.5f - 15), new Color(0, colorG, 1, 0f), new Vector3(1, value * 0.73f + timeValue * 0.75f, zValue));
+ bars.Add(Position + new Vector2(12 * (1 - value) + xValue, t * 3.5f - 15), new Color(0, colorG, 1, 0f), new Vector3(0, value * 0.73f + timeValue * 0.75f, zValue));
+ bars.Add(Position + new Vector2(-25 * (1 - value) + xValue, t * 3.5f - 15), new Color(0, colorG, 1, 0f), new Vector3(1, value * 0.73f + timeValue * 0.75f, zValue));
colorG = MathF.Pow(value, 0.4f);
}
- bars.Add(position + new Vector2(12 * (1 - value) + xValue, t * 2.5f - 15), new Color(colorR, colorG, value, 0f), new Vector3(0, value * 0.73f + timeValue * 0.75f, zValue));
- bars.Add(position + new Vector2(-25 * (1 - value) + xValue, t * 2.5f - 15), new Color(colorR, colorG, value, 0f), new Vector3(1, value * 0.73f + timeValue * 0.75f, zValue));
+ bars.Add(Position + new Vector2(12 * (1 - value) + xValue, t * 2.5f - 15), new Color(colorR, colorG, value, 0f), new Vector3(0, value * 0.73f + timeValue * 0.75f, zValue));
+ bars.Add(Position + new Vector2(-25 * (1 - value) + xValue, t * 2.5f - 15), new Color(colorR, colorG, value, 0f), new Vector3(1, value * 0.73f + timeValue * 0.75f, zValue));
}
for (int t = 0; t < 20; t++)
{
@@ -197,8 +205,8 @@ public override void Draw()
colorG = MathF.Pow(value, 0.4f);
}
float xValue = 3 * MathF.Sin(value * 32 + timeValue * 16) * value - value * 10;
- bars.Add(position + new Vector2(-20 * (1 - value) + xValue, t * 3.5f - 15), new Color(colorR, colorG, value, 0f), new Vector3(0, value * 0.54f + timeValue * 0.95f, zValue));
- bars.Add(position + new Vector2(22 * (1 - value) + xValue, t * 3.5f - 15), new Color(colorR, colorG, value, 0f), new Vector3(1, value * 0.54f + timeValue * 0.95f, zValue));
+ bars.Add(Position + new Vector2(-20 * (1 - value) + xValue, t * 3.5f - 15), new Color(colorR, colorG, value, 0f), new Vector3(0, value * 0.54f + timeValue * 0.95f, zValue));
+ bars.Add(Position + new Vector2(22 * (1 - value) + xValue, t * 3.5f - 15), new Color(colorR, colorG, value, 0f), new Vector3(1, value * 0.54f + timeValue * 0.95f, zValue));
}
for (int t = 0; t < 20; t++)
{
@@ -213,8 +221,8 @@ public override void Draw()
colorG = MathF.Pow(value, 0.4f);
}
float xValue = 3 * MathF.Sin(value * 32 + timeValue * 16) * value + value * 40;
- bars.Add(position + new Vector2(-7 * (1 - value) + xValue, t * 2.5f - 15), new Color(colorR, colorG, value, 0f), new Vector3(0, value * 0.63f + timeValue * 1.05f, zValue));
- bars.Add(position + new Vector2(25 * (1 - value) + xValue, t * 2.5f - 15), new Color(colorR, colorG, value, 0f), new Vector3(1, value * 0.63f + timeValue * 1.05f, zValue));
+ bars.Add(Position + new Vector2(-7 * (1 - value) + xValue, t * 2.5f - 15), new Color(colorR, colorG, value, 0f), new Vector3(0, value * 0.63f + timeValue * 1.05f, zValue));
+ bars.Add(Position + new Vector2(25 * (1 - value) + xValue, t * 2.5f - 15), new Color(colorR, colorG, value, 0f), new Vector3(1, value * 0.63f + timeValue * 1.05f, zValue));
}
Ins.Batch.Draw(bars, PrimitiveType.TriangleStrip);
}
diff --git a/Sources/Modules/CagedDomain/Tiles/HangingTiles/HangingFluoriteLamp.cs b/Sources/Modules/CagedDomain/Tiles/HangingTiles/HangingFluoriteLamp.cs
index ab0b8af88..b42a2b1dc 100644
--- a/Sources/Modules/CagedDomain/Tiles/HangingTiles/HangingFluoriteLamp.cs
+++ b/Sources/Modules/CagedDomain/Tiles/HangingTiles/HangingFluoriteLamp.cs
@@ -9,7 +9,7 @@ public class HangingFluoriteLamp : HangingTile
public override void PostSetDefaults()
{
RopeUnitMass = 0.6f;
- SingleLampMass = 200f;
+ HangingItemMass = 200f;
MaxWireStyle = 1;
Elasticity = 70f;
}
diff --git a/Sources/Modules/CagedDomain/Tiles/OnWallTiles/MorphoFrame.cs b/Sources/Modules/CagedDomain/Tiles/OnWallTiles/MorphoFrame.cs
new file mode 100644
index 000000000..74d77d7e4
--- /dev/null
+++ b/Sources/Modules/CagedDomain/Tiles/OnWallTiles/MorphoFrame.cs
@@ -0,0 +1,33 @@
+using Terraria.ObjectData;
+
+namespace Everglow.CagedDomain.Tiles.OnWallTiles;
+
+public class MorphoFrame : ModTile
+{
+ public override void SetStaticDefaults()
+ {
+ Main.tileFrameImportant[Type] = true;
+ Main.tileLighted[Type] = true;
+ Main.tileLavaDeath[Type] = false;
+ Main.tileNoAttach[Type] = false;
+ Main.tileWaterDeath[Type] = false;
+
+ TileObjectData.newTile.CopyFrom(TileObjectData.Style3x3Wall);
+ TileObjectData.newTile.Height = 3;
+ TileObjectData.newTile.Width = 3;
+ TileObjectData.newTile.CoordinateHeights = new int[3];
+ Array.Fill(TileObjectData.newTile.CoordinateHeights, 16);
+ TileObjectData.newTile.StyleHorizontal = true;
+ TileObjectData.newTile.LavaDeath = false;
+
+ TileObjectData.addTile(Type);
+ DustType = DustID.Glass;
+ AddMapEntry(new Color(21, 21, 22));
+ }
+
+ public override void NumDust(int i, int j, bool fail, ref int num)
+ {
+ num = 0;
+ base.NumDust(i, j, fail, ref num);
+ }
+}
diff --git a/Sources/Modules/CagedDomain/Tiles/OnWallTiles/MorphoFrame.png b/Sources/Modules/CagedDomain/Tiles/OnWallTiles/MorphoFrame.png
new file mode 100644
index 000000000..34a5f927f
Binary files /dev/null and b/Sources/Modules/CagedDomain/Tiles/OnWallTiles/MorphoFrame.png differ
diff --git a/Sources/Modules/CagedDomain/Tiles/PierWithSlabsTop.cs b/Sources/Modules/CagedDomain/Tiles/PierWithSlabsTop.cs
index e1402d73d..b3ef7d58f 100644
--- a/Sources/Modules/CagedDomain/Tiles/PierWithSlabsTop.cs
+++ b/Sources/Modules/CagedDomain/Tiles/PierWithSlabsTop.cs
@@ -1,13 +1,16 @@
+using Everglow.Commons.TileHelper;
using Terraria.DataStructures;
using Terraria.Enums;
using Terraria.ObjectData;
namespace Everglow.CagedDomain.Tiles;
-public class PierWithSlabsTop : ModTile
+public class PierWithSlabsTop : ShapeDataTile
{
public override void SetStaticDefaults()
{
+ TotalWidth = 13;
+ TotalHeight = 8;
Main.tileFrameImportant[Type] = true;
Main.tileSolid[Type] = true;
Main.tileBlockLight[Type] = false;
@@ -15,35 +18,29 @@ public override void SetStaticDefaults()
TileObjectData.newTile.CopyFrom(TileObjectData.Style1x1);
TileObjectData.newTile.Height = 8;
TileObjectData.newTile.Width = 13;
- TileObjectData.newTile.CoordinateHeights = new int[]
- {
- 16,
- 16,
- 16,
- 16,
- 16,
- 16,
- 16,
- 16
- };
+ TileObjectData.newTile.CoordinateHeights = new int[8];
+ Array.Fill(TileObjectData.newTile.CoordinateHeights, 16);
TileObjectData.newTile.AnchorTop = new AnchorData(AnchorType.SolidTile, TileObjectData.newTile.Width, 0);
- TileObjectData.newAlternate.AnchorAlternateTiles = new[] { (int)Type, (int)ModContent.TileType() };
- TileObjectData.newTile.AnchorBottom = default;
- TileObjectData.newTile.Origin = new Point16(1, 0);
+ TileObjectData.newTile.AnchorBottom = AnchorData.Empty;
+ TileObjectData.newTile.Origin = new Point16(6, 0);
TileObjectData.addTile(Type);
+
// Etc
AddMapEntry(new Color(86, 86, 86));
}
+
public override void NumDust(int i, int j, bool fail, ref int num)
{
num = 0;
}
- public override bool CanExplode(int i, int j)
- {
- return false;
- }
- public override bool CanKillTile(int i, int j, ref bool blockDamaged)
- {
- return false;
- }
+
+ //public override bool CanExplode(int i, int j)
+ //{
+ // return false;
+ //}
+
+ //public override bool CanKillTile(int i, int j, ref bool blockDamaged)
+ //{
+ // return false;
+ //}
}
diff --git a/Sources/Modules/CagedDomain/Tiles/PierWithSlabsTop_shape.bmp b/Sources/Modules/CagedDomain/Tiles/PierWithSlabsTop_shape.bmp
new file mode 100644
index 000000000..43c7b05a3
Binary files /dev/null and b/Sources/Modules/CagedDomain/Tiles/PierWithSlabsTop_shape.bmp differ
diff --git a/Sources/Modules/CagedDomain/Tiles/SluiceWallLamp.cs b/Sources/Modules/CagedDomain/Tiles/SluiceWallLamp.cs
new file mode 100644
index 000000000..364bc7292
--- /dev/null
+++ b/Sources/Modules/CagedDomain/Tiles/SluiceWallLamp.cs
@@ -0,0 +1,55 @@
+using Everglow.CagedDomain.Dusts;
+using Everglow.Commons.Utilities;
+using Terraria.DataStructures;
+using Terraria.Enums;
+using Terraria.ObjectData;
+
+namespace Everglow.CagedDomain.Tiles;
+
+public class SluiceWallLamp : ModTile
+{
+ public override void SetStaticDefaults()
+ {
+ Main.tileFrameImportant[Type] = true;
+ Main.tileLighted[Type] = true;
+ Main.tileLavaDeath[Type] = false;
+ Main.tileNoAttach[Type] = false;
+ Main.tileWaterDeath[Type] = false;
+
+ TileObjectData.newTile.CopyFrom(TileObjectData.Style3x3Wall);
+ TileObjectData.newTile.Height = 2;
+ TileObjectData.newTile.Width = 3;
+
+ TileObjectData.newTile.CoordinateHeights = new int[2];
+ Array.Fill(TileObjectData.newTile.CoordinateHeights, 16);
+ TileObjectData.newTile.StyleHorizontal = true;
+ TileObjectData.newTile.LavaDeath = true;
+ TileObjectData.newTile.Origin = new(1, 0);
+
+ TileObjectData.addTile(Type);
+ DustType = ModContent.DustType();
+ AddMapEntry(new Color(255, 217, 142));
+ }
+
+ public override void ModifyLight(int i, int j, ref float r, ref float g, ref float b)
+ {
+ var tile = Main.tile[i, j];
+ if (tile.TileFrameX < 54)
+ {
+ r = 1.3f;
+ g = 1.1f;
+ b = 0.6f;
+ }
+ else
+ {
+ r = 0f;
+ g = 0f;
+ b = 0f;
+ }
+ }
+
+ public override void HitWire(int i, int j)
+ {
+ FurnitureUtils.LightHitwire(i, j, Type, 3, 2);
+ }
+}
diff --git a/Sources/Modules/CagedDomain/Tiles/SluiceWallLamp.png b/Sources/Modules/CagedDomain/Tiles/SluiceWallLamp.png
new file mode 100644
index 000000000..798a9a109
Binary files /dev/null and b/Sources/Modules/CagedDomain/Tiles/SluiceWallLamp.png differ
diff --git a/Sources/Modules/Example/Items/ExampleRopeItem.cs b/Sources/Modules/Example/Items/ExampleRopeItem.cs
index 88bb5ea88..6184afaf4 100644
--- a/Sources/Modules/Example/Items/ExampleRopeItem.cs
+++ b/Sources/Modules/Example/Items/ExampleRopeItem.cs
@@ -18,7 +18,7 @@ public override void HoldItem(Player player)
AddRope();
}
ItemRope.Masses[0].Position = Main.MouseWorld;
- ItemRope.ApplyForce_Gravity();
+ //ItemRope.ApplyForce_Gravity();
ItemRope.ApplyForce_VelocityDecay(0.2f);
// Experimental codes.
@@ -82,7 +82,7 @@ public override void PostDrawInInventory(SpriteBatch spriteBatch, Vector2 positi
public void AddRope()
{
- ItemRope = Rope.Create_Vine(Main.MouseWorld, 10, 2, 1);
+ ItemRope = Rope.Create_Vine(Main.MouseWorld, 30, 2, 1, 15);
// Rope.Create_Fixed_StartPos(Main.MouseWorld, 20, 5, 0.5f, 20);
EularSys.AddMassSpringMesh(ItemRope);
diff --git a/Sources/Modules/Minortopography/GiantPinetree/GiantPinetreeGenPass.cs b/Sources/Modules/Minortopography/GiantPinetree/GiantPinetreeGenPass.cs
index 223b50a13..8b532ba60 100644
--- a/Sources/Modules/Minortopography/GiantPinetree/GiantPinetreeGenPass.cs
+++ b/Sources/Modules/Minortopography/GiantPinetree/GiantPinetreeGenPass.cs
@@ -151,7 +151,7 @@ public static void BuildGiantPinetree()
RemoveDestroyedTrees(positonX, positonY);
// 平滑木头部分
- SmoothTile(positonX - 60, positonY - 20, 120, 250, ModContent.TileType());
+ SmoothTile_XXYY(positonX - 60, positonY - 20, 120, 250, ModContent.TileType());
DistributePineCone(new Point16(positonX, positonY - 10), 40, 40);
DistributePineCone(new Point16(positonX, positonY - 60), 20, 20);
DistributePineNeedle(new Point16(positonX, positonY), 120, 120);
@@ -1219,7 +1219,7 @@ public static void RemoveDestroyedTrees(int i, int j)
///
///
///
- private static void SmoothTile(int x = 0, int y = 0, int width = 0, int height = 0, int tileType = -1)
+ private static void SmoothTile_XXYY(int x = 0, int y = 0, int width = 0, int height = 0, int tileType = -1)
{
for (int i = 0; i < width; i += 1)
{
diff --git a/Sources/Modules/Yggdrasil/CityOfMagicFlute/Projectiles/Ranged/TerraViewerHowitzer_grenade_fall_explosion.cs b/Sources/Modules/Yggdrasil/CityOfMagicFlute/Projectiles/Ranged/TerraViewerHowitzer_grenade_fall_explosion.cs
index d2589cbd2..0f4d2870a 100644
--- a/Sources/Modules/Yggdrasil/CityOfMagicFlute/Projectiles/Ranged/TerraViewerHowitzer_grenade_fall_explosion.cs
+++ b/Sources/Modules/Yggdrasil/CityOfMagicFlute/Projectiles/Ranged/TerraViewerHowitzer_grenade_fall_explosion.cs
@@ -24,12 +24,11 @@ public override void SetDefaults()
Projectile.usesLocalNPCImmunity = true;
Projectile.localNPCHitCooldown = 20;
Projectile.DamageType = DamageClass.Magic;
- ProjectileID.Sets.DrawScreenCheckFluff[Projectile.type] = 14400;
}
- public void Spark()
+ public void Spark(int count)
{
- for (int g = 0; g < 120; g++)
+ for (int x = 0; x < count; x++)
{
Vector2 newVelocity = new Vector2(0, Main.rand.NextFloat(2f, 22f)).RotatedByRandom(MathHelper.TwoPi);
var spark = new FireSparkDust
@@ -47,56 +46,65 @@ public void Spark()
}
}
- public void FlameII()
+ public void FlameII(int count)
{
- var newVelocity = new Vector2(0, -10);
- Vector2 addPos = new Vector2(Main.rand.NextFloat(40), 0).RotatedByRandom(MathHelper.TwoPi);
- var fire = new FireDust
+ for (int x = 0; x < count; x++)
{
- velocity = newVelocity,
- Active = true,
- Visible = true,
- position = Projectile.Center + addPos - newVelocity,
- maxTime = Main.rand.Next(30, 45),
- scale = Main.rand.NextFloat(20f, 60f),
- rotation = Main.rand.NextFloat(6.283f),
- ai = new float[] { Main.rand.NextFloat(0.0f, 0.93f), addPos.X * 0.002f },
- };
- Ins.VFXManager.Add(fire);
+ var newVelocity = new Vector2(0, -10);
+ Vector2 addPos = new Vector2(Main.rand.NextFloat(40), 0).RotatedByRandom(MathHelper.TwoPi);
+ var fire = new FireDust
+ {
+ velocity = newVelocity,
+ Active = true,
+ Visible = true,
+ position = Projectile.Center + addPos - newVelocity,
+ maxTime = Main.rand.Next(30, 45),
+ scale = Main.rand.NextFloat(20f, 60f),
+ rotation = Main.rand.NextFloat(6.283f),
+ ai = new float[] { Main.rand.NextFloat(0.0f, 0.93f), addPos.X * 0.002f },
+ };
+ Ins.VFXManager.Add(fire);
+ }
}
- public void LargeFlame()
+ public void LargeFlame(int count)
{
- Vector2 newVelocity = new Vector2(0, Main.rand.NextFloat(2f, 8f)).RotatedByRandom(MathHelper.TwoPi);
- var somg = new MissleFlameDust
+ for (int x = 0; x < count; x++)
{
- velocity = newVelocity,
- Active = true,
- Visible = true,
- position = Projectile.Center + new Vector2(Main.rand.NextFloat(40), 0).RotatedByRandom(6.283),
- maxTime = Main.rand.Next(60, 75),
- scale = Main.rand.NextFloat(80f, 160f),
- rotation = Main.rand.NextFloat(6.283f),
- ai = new float[] { Main.rand.NextFloat(0.0f, 0.93f), 0 },
- };
- Ins.VFXManager.Add(somg);
+ Vector2 newVelocity = new Vector2(0, MathF.Sqrt(Main.rand.NextFloat(1f)) * 12f).RotatedByRandom(MathHelper.TwoPi);
+ var somg = new MissleFlameDust
+ {
+ velocity = newVelocity,
+ Active = true,
+ Visible = true,
+ position = Projectile.Center + new Vector2(Main.rand.NextFloat(6), 0).RotatedByRandom(6.283),
+ maxTime = Main.rand.Next(90, 120),
+ scale = Main.rand.NextFloat(24f, 36f),
+ rotation = Main.rand.NextFloat(6.283f),
+ ai = new float[] { Main.rand.NextFloat(0.0f, 0.93f), 0 },
+ };
+ Ins.VFXManager.Add(somg);
+ }
}
- public void SmallFlame()
+ public void SmallFlame(int count)
{
- Vector2 newVelocity = new Vector2(0, Main.rand.NextFloat(2f, 8f)).RotatedByRandom(MathHelper.TwoPi);
- var somg = new MissleFlameDust
+ for (int x = 0; x < count; x++)
{
- velocity = newVelocity,
- Active = true,
- Visible = true,
- position = Projectile.Center + new Vector2(Main.rand.NextFloat(60), 0).RotatedByRandom(6.283),
- maxTime = Main.rand.Next(30, 45),
- scale = Main.rand.NextFloat(50f, 90f),
- rotation = Main.rand.NextFloat(6.283f),
- ai = new float[] { Main.rand.NextFloat(0.0f, 0.93f), 0 },
- };
- Ins.VFXManager.Add(somg);
+ Vector2 newVelocity = new Vector2(0, MathF.Sqrt(Main.rand.NextFloat(1f)) * 8f).RotatedByRandom(MathHelper.TwoPi);
+ var somg = new MissleFlameDust
+ {
+ velocity = newVelocity,
+ Active = true,
+ Visible = true,
+ position = Projectile.Center + new Vector2(Main.rand.NextFloat(4), 0).RotatedByRandom(6.283),
+ maxTime = Main.rand.Next(50, 70),
+ scale = Main.rand.NextFloat(12f, 20f),
+ rotation = Main.rand.NextFloat(6.283f),
+ ai = new float[] { Main.rand.NextFloat(0.0f, 0.93f), 0 },
+ };
+ Ins.VFXManager.Add(somg);
+ }
}
public override void OnSpawn(IEntitySource source)
@@ -109,16 +117,9 @@ public override void AI()
Projectile.velocity *= 0;
if (Projectile.timeLeft == 190)
{
- Spark();
-
- for (int x = 0; x < 35; x++)
- {
- LargeFlame();
- }
- for (int x = 0; x < 75; x++)
- {
- SmallFlame();
- }
+ Spark(120);
+ LargeFlame(35);
+ SmallFlame(75);
}
if (Projectile.timeLeft <= 190)
{
@@ -130,10 +131,7 @@ public override void AI()
}
if (Projectile.timeLeft == 180)
{
- for (int x = 0; x < 35; x++)
- {
- FlameII();
- }
+ FlameII(35);
}
}
@@ -199,6 +197,6 @@ public void DrawWarp(VFXBatch spriteBatch)
}
Texture2D t = Commons.ModAsset.Trail.Value;
- DrawTexCircle_VFXBatch(spriteBatch, MathF.Sqrt(value) * 150f * Projectile.ai[0], 15 * (1 - value) * Projectile.ai[0], new Color(colorV, colorV * 0.012f, colorV, 0f), Projectile.Center - Main.screenPosition, t, Math.PI * 0.5);
+ DrawTexCircle_VFXBatch(spriteBatch, MathF.Sqrt(value) * 150f * Projectile.ai[0], 15 * (1 - value) * Projectile.ai[0], new Color(colorV, colorV * 0.6f, colorV, 0f), Projectile.Center - Main.screenPosition, t, Math.PI * 0.5);
}
}
diff --git a/Sources/Modules/Yggdrasil/Common/BackgroundManager/BackgroundManager.cs b/Sources/Modules/Yggdrasil/Common/BackgroundManager/BackgroundManager.cs
index 1324bfe67..b54141cb2 100644
--- a/Sources/Modules/Yggdrasil/Common/BackgroundManager/BackgroundManager.cs
+++ b/Sources/Modules/Yggdrasil/Common/BackgroundManager/BackgroundManager.cs
@@ -37,9 +37,14 @@ public void SpecialDraw(SpriteBatch spriteBatch)
}
}
- public static void QuickDrawBG(Texture2D tex, float depth, Vector2 anchorWorldPos, Color baseColor, int yWorldCoordMin, int yWorldCoordMax, bool xClamp = false, bool yClamp = true)
+ public static void DrawBG_RestrictXY(Texture2D tex, float depth, Vector2 anchorWorldPos, Color baseColor, int xWorldCoordMin, int xWorldCoordMax, int yWorldCoordMin, int yWorldCoordMax, bool xClamp = false, bool yClamp = true)
{
- QuickDrawBG(tex, GetDrawFrame(tex, depth, anchorWorldPos), baseColor, yWorldCoordMin, yWorldCoordMax, false, true);
+ DrawBG_RestrictXY(tex, GetDrawFrame(tex, depth, anchorWorldPos), baseColor, xWorldCoordMin, xWorldCoordMax, yWorldCoordMin, yWorldCoordMax, xClamp, yClamp);
+ }
+
+ public static void DrawBG_RestrictY(Texture2D tex, float depth, Vector2 anchorWorldPos, Color baseColor, int yWorldCoordMin, int yWorldCoordMax, bool xClamp = false, bool yClamp = true)
+ {
+ DrawBG_RestrictY(tex, GetDrawFrame(tex, depth, anchorWorldPos), baseColor, yWorldCoordMin, yWorldCoordMax, xClamp, yClamp);
}
///
@@ -53,26 +58,26 @@ public static void QuickDrawBG(Texture2D tex, float depth, Vector2 anchorWorldPo
///
///
///
- public static void QuickDrawBG(Texture2D tex, Rectangle drawFrame, Color baseColor, int yWorldCoordMin, int yWorldCoordMax, bool xClamp = false, bool yClamp = true)
+ public static void DrawBG_RestrictY(Texture2D tex, Rectangle drawFrame, Color baseColor, int yWorldCoordMin, int yWorldCoordMax, bool xClamp = false, bool yClamp = true)
{
SpriteBatchState sBS = GraphicsUtils.GetState(Main.spriteBatch).Value;
Main.spriteBatch.End();
Main.spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied, SamplerState.PointWrap, DepthStencilState.Default, RasterizerState.CullNone, null, Main.GameViewMatrix.TransformationMatrix);
- Effect bgW = ModAsset.BackgroundXWarp.Value;
+ Effect bg_wrapEffect = ModAsset.BackgroundXWarp.Value;
if (xClamp && yClamp)
{
- bgW = ModAsset.BackgroundXYClamp.Value;
+ bg_wrapEffect = ModAsset.BackgroundXYClamp.Value;
}
if (xClamp && !yClamp)
{
- bgW = ModAsset.BackgroundYWarp.Value;
+ bg_wrapEffect = ModAsset.BackgroundYWarp.Value;
}
if (!xClamp && !yClamp)
{
- bgW = ModAsset.BackgroundXYWarp.Value;
+ bg_wrapEffect = ModAsset.BackgroundXYWarp.Value;
}
var projection = Matrix.CreateOrthographicOffCenter(0, Main.screenWidth, Main.screenHeight, 0, 0, 1);
@@ -81,9 +86,9 @@ public static void QuickDrawBG(Texture2D tex, Rectangle drawFrame, Color baseCol
projection = Matrix.CreateOrthographicOffCenter(0, Main.screenWidth, 0, Main.screenHeight, 0, 1);
}
- bgW.Parameters["uTransform"].SetValue(projection);
- bgW.Parameters["uTime"].SetValue(0.34f);
- bgW.CurrentTechnique.Passes[0].Apply();
+ bg_wrapEffect.Parameters["uTransform"].SetValue(projection);
+ bg_wrapEffect.Parameters["uTime"].SetValue(0.34f);
+ bg_wrapEffect.CurrentTechnique.Passes[0].Apply();
// å¤„ç†æŽ‰è¶…å‡ºåœ°å›¾ç•Œé™çš„部分
int drawMaxY = Main.screenHeight;
@@ -101,7 +106,7 @@ public static void QuickDrawBG(Texture2D tex, Rectangle drawFrame, Color baseCol
yClampValueUp = drawMinY / (float)Main.screenHeight;
}
- var CloseII = new List
+ var bg_vertices = new List
{
new Vertex2D(new Vector2(0, drawMinY), baseColor, new Vector3(drawFrame.X / (float)tex.Width, (drawFrame.Y + drawFrame.Height * yClampValueUp) / tex.Height, 0)),
new Vertex2D(new Vector2(Main.screenWidth, drawMinY), baseColor, new Vector3((drawFrame.X + drawFrame.Width) / (float)tex.Width, (drawFrame.Y + drawFrame.Height * yClampValueUp) / tex.Height, 0)),
@@ -111,11 +116,99 @@ public static void QuickDrawBG(Texture2D tex, Rectangle drawFrame, Color baseCol
new Vertex2D(new Vector2(Main.screenWidth, drawMinY), baseColor, new Vector3((drawFrame.X + drawFrame.Width) / (float)tex.Width, (drawFrame.Y + drawFrame.Height * yClampValueUp) / tex.Height, 0)),
new Vertex2D(new Vector2(Main.screenWidth, drawMaxY), baseColor, new Vector3((drawFrame.X + drawFrame.Width) / (float)tex.Width, (drawFrame.Y + drawFrame.Height * yClampValueDown) / tex.Height, 0)),
};
- if (CloseII.Count > 2)
+ if (bg_vertices.Count > 2)
+ {
+ Main.graphics.GraphicsDevice.Textures[0] = tex;
+ Main.graphics.GraphicsDevice.SamplerStates[0] = SamplerState.PointWrap;
+ Main.graphics.GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, bg_vertices.ToArray(), 0, 2);
+ }
+ Main.spriteBatch.End();
+ Main.spriteBatch.Begin(sBS);
+ }
+
+ public static void DrawBG_RestrictXY(Texture2D tex, Rectangle drawFrame, Color baseColor, int xWorldCoordMin, int xWorldCoordMax, int yWorldCoordMin, int yWorldCoordMax, bool xClamp = false, bool yClamp = true)
+ {
+ SpriteBatchState sBS = GraphicsUtils.GetState(Main.spriteBatch).Value;
+ Main.spriteBatch.End();
+ Main.spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied, SamplerState.PointWrap, DepthStencilState.Default, RasterizerState.CullNone, null, Main.GameViewMatrix.TransformationMatrix);
+
+ Effect bg_wrapEffect = ModAsset.BackgroundXWarp.Value;
+ if (xClamp && yClamp)
+ {
+ bg_wrapEffect = ModAsset.BackgroundXYClamp.Value;
+ }
+
+ if (xClamp && !yClamp)
+ {
+ bg_wrapEffect = ModAsset.BackgroundYWarp.Value;
+ }
+
+ if (!xClamp && !yClamp)
+ {
+ bg_wrapEffect = ModAsset.BackgroundXYWarp.Value;
+ }
+
+ var projection = Matrix.CreateOrthographicOffCenter(0, Main.screenWidth, Main.screenHeight, 0, 0, 1);
+ if (Main.LocalPlayer.gravDir == -1)
+ {
+ projection = Matrix.CreateOrthographicOffCenter(0, Main.screenWidth, 0, Main.screenHeight, 0, 1);
+ }
+
+ bg_wrapEffect.Parameters["uTransform"].SetValue(projection);
+ bg_wrapEffect.Parameters["uTime"].SetValue(0.34f);
+ bg_wrapEffect.CurrentTechnique.Passes[0].Apply();
+
+ // å¤„ç†æŽ‰è¶…å‡ºåœ°å›¾ç•Œé™çš„部分
+
+ int drawMaxX = Main.screenWidth;
+ int drawMinX = 0;
+ float xClampValueUp = 0f;
+ float xClampValueDown = 1f;
+ if (Main.screenPosition.X + Main.screenWidth > xWorldCoordMax)
+ {
+ drawMaxX = xWorldCoordMax - (int)Main.screenPosition.X;
+ xClampValueDown = (float)drawMaxX / Main.screenWidth;
+ }
+ if (Main.screenPosition.X < xWorldCoordMin)
+ {
+ drawMinX = xWorldCoordMin - (int)Main.screenPosition.X;
+ xClampValueUp = drawMinX / (float)Main.screenWidth;
+ }
+
+ int drawMaxY = Main.screenHeight;
+ int drawMinY = 0;
+ float yClampValueUp = 0f;
+ float yClampValueDown = 1f;
+ if (Main.screenPosition.Y + Main.screenHeight > yWorldCoordMax)
+ {
+ drawMaxY = yWorldCoordMax - (int)Main.screenPosition.Y;
+ yClampValueDown = (float)drawMaxY / Main.screenHeight;
+ }
+ if (Main.screenPosition.Y < yWorldCoordMin)
+ {
+ drawMinY = yWorldCoordMin - (int)Main.screenPosition.Y;
+ yClampValueUp = drawMinY / (float)Main.screenHeight;
+ }
+ float xCoord0 = (drawFrame.X + drawFrame.Width * xClampValueUp) / tex.Width;
+ float xCoord1 = (drawFrame.X + drawFrame.Width * xClampValueDown) / tex.Width;
+ float yCoord0 = (drawFrame.Y + drawFrame.Height * yClampValueUp) / tex.Height;
+ float yCoord1 = (drawFrame.Y + drawFrame.Height * yClampValueDown) / tex.Height;
+
+ var bg_vertices = new List
+ {
+ new Vertex2D(new Vector2(drawMinX, drawMinY), baseColor, new Vector3(xCoord0, yCoord0, 0)),
+ new Vertex2D(new Vector2(drawMaxX, drawMinY), baseColor, new Vector3(xCoord1, yCoord0, 0)),
+ new Vertex2D(new Vector2(drawMinX, drawMaxY), baseColor, new Vector3(xCoord0, yCoord1, 0)),
+
+ new Vertex2D(new Vector2(drawMinX, drawMaxY), baseColor, new Vector3(xCoord0, yCoord1, 0)),
+ new Vertex2D(new Vector2(drawMaxX, drawMinY), baseColor, new Vector3(xCoord1, yCoord0, 0)),
+ new Vertex2D(new Vector2(drawMaxX, drawMaxY), baseColor, new Vector3(xCoord1, yCoord1, 0)),
+ };
+ if (bg_vertices.Count > 2)
{
Main.graphics.GraphicsDevice.Textures[0] = tex;
Main.graphics.GraphicsDevice.SamplerStates[0] = SamplerState.PointWrap;
- Main.graphics.GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, CloseII.ToArray(), 0, 2);
+ Main.graphics.GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, bg_vertices.ToArray(), 0, 2);
}
Main.spriteBatch.End();
Main.spriteBatch.Begin(sBS);
@@ -302,10 +395,10 @@ public static void DrawWaterfall(Vector2 drawCenter, float width, float height,
projection = Matrix.CreateOrthographicOffCenter(0, Main.screenWidth, 0, Main.screenHeight, 0, 1);
}
- Effect bgW = ModAsset.BackgroundYWarp.Value;
- bgW.Parameters["uTransform"].SetValue(projection);
- bgW.Parameters["uTime"].SetValue(0.34f);
- bgW.CurrentTechnique.Passes[0].Apply();
+ Effect bg_wrapEffect = ModAsset.BackgroundYWarp.Value;
+ bg_wrapEffect.Parameters["uTransform"].SetValue(projection);
+ bg_wrapEffect.Parameters["uTime"].SetValue(0.34f);
+ bg_wrapEffect.CurrentTechnique.Passes[0].Apply();
float Time = (float)-Main.timeForVisualEffects / 40f;
var WaterFallVertex = new List();
diff --git a/Sources/Modules/Yggdrasil/Common/Fish/FishGlobalItem.cs b/Sources/Modules/Yggdrasil/Common/Fish/FishGlobalItem.cs
index 97c7066a4..fdf6d5022 100644
--- a/Sources/Modules/Yggdrasil/Common/Fish/FishGlobalItem.cs
+++ b/Sources/Modules/Yggdrasil/Common/Fish/FishGlobalItem.cs
@@ -31,6 +31,11 @@ public class FishGlobalItem : GlobalItem
///
public bool Hookable = false;
+ ///
+ /// 生æˆè¿™ä¸ªç‰©å“çš„ FishableItem
+ ///
+ public FishableItem FishableInfo;
+
public int HoverTick = 0;
public override bool InstancePerEntity => true;
@@ -148,6 +153,26 @@ public void CheckRightClick(Item item)
}
}
+ public void UpdateOnVanillaLiquid(Item item, ref float gravity)
+ {
+ Point itemPos = item.Center.ToTileCoordinates();
+ byte liquid = Main.tile[itemPos].LiquidAmount;
+ if (liquid > 0)
+ {
+ float percent = liquid / 255f;
+ float liqY = percent * 16f + itemPos.Y * 16f;
+ float delta = item.Center.Y - liqY;
+ if (delta < 0 || liquid == 255)
+ {
+ float ratio = Main.rand.NextFloat(1) + 0.5f;
+ float buoyancy = Math.Clamp(-delta / item.height * 2, 0, 1);
+ gravity *= -ratio * buoyancy;
+ item.velocity.Y *= 0.9f;
+ item.velocity.X = FloatSpeed;
+ }
+ }
+ }
+
public override void Update(Item item, ref float gravity, ref float maxFallSpeed)
{
if (!IsFishable(item))
@@ -162,21 +187,9 @@ public override void Update(Item item, ref float gravity, ref float maxFallSpeed
Hookable = false;
return;
}
- Point itemPos = item.Center.ToTileCoordinates();
- byte liquid = Main.tile[itemPos].LiquidAmount;
- if (liquid > 0)
+ else
{
- float percent = liquid / 255f;
- float liqY = percent * 16f + itemPos.Y * 16f;
- float delta = item.Center.Y - liqY;
- if (delta < 0)
- {
- float ratio = Main.rand.NextFloat(1) + .5f;
- float buoyancy = Math.Clamp(-delta / item.height * 2, 0, 1);
- gravity *= -ratio * buoyancy;
- item.velocity.Y *= .9f;
- item.velocity.X = FloatSpeed;
- }
+ UpdateOnVanillaLiquid(item, ref gravity);
}
CheckHover(item);
CheckHookable(item);
@@ -184,6 +197,24 @@ public override void Update(Item item, ref float gravity, ref float maxFallSpeed
base.Update(item, ref gravity, ref maxFallSpeed);
}
+ public override void GrabRange(Item item, Player player, ref int grabRange)
+ {
+ if (Fishable && HookedBy == null)
+ {
+ grabRange = 0;
+ }
+ base.GrabRange(item, player, ref grabRange);
+ }
+
+ public override bool CanPickup(Item item, Player player)
+ {
+ if (Fishable && HookedBy == null)
+ {
+ return false;
+ }
+ return base.CanPickup(item, player);
+ }
+
public override void PostDrawInWorld(Item item, SpriteBatch spriteBatch, Color lightColor, Color alphaColor, float rotation, float scale, int whoAmI)
{
Vector2 basePos = item.Center - Main.screenPosition;
@@ -194,9 +225,9 @@ public override void PostDrawInWorld(Item item, SpriteBatch spriteBatch, Color l
}
if (Hovered && Hookable)
{
- var font = FontAssets.MouseText.Value;
- string hint = "Right click to hook";
- Vector2 size = font.MeasureString(hint);
+ // var font = FontAssets.MouseText.Value;
+ // string hint = "Right click to hook";
+ // Vector2 size = font.MeasureString(hint);
// spriteBatch.DrawString(font, hint, basePos - size / 2 - new Vector2(0, item.height / 2 + 20), Color.Gold);
}
base.PostDrawInWorld(item, spriteBatch, lightColor, alphaColor, rotation, scale, whoAmI);
diff --git a/Sources/Modules/Yggdrasil/Common/Fish/FishGlobalProjectile.cs b/Sources/Modules/Yggdrasil/Common/Fish/FishGlobalProjectile.cs
deleted file mode 100644
index f442638cf..000000000
--- a/Sources/Modules/Yggdrasil/Common/Fish/FishGlobalProjectile.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Everglow.Yggdrasil.Common.Fish;
-
-public class FishGlobalProjectile : GlobalProjectile
-{
- public override void PostAI(Projectile projectile)
- {
- }
-}
diff --git a/Sources/Modules/Yggdrasil/Common/Fish/FishSystem.cs b/Sources/Modules/Yggdrasil/Common/Fish/FishSystem.cs
index ada117002..ad7d0c8fe 100644
--- a/Sources/Modules/Yggdrasil/Common/Fish/FishSystem.cs
+++ b/Sources/Modules/Yggdrasil/Common/Fish/FishSystem.cs
@@ -1,10 +1,9 @@
-using Everglow.Yggdrasil.WorldGeneration;
-
namespace Everglow.Yggdrasil.Common.Fish;
public class FishSystem : ModSystem
{
public static Dictionary> FishMap = [];
+ public static HashSet LiquidList = [];
///
/// 注册一ç§å¯ä»¥è¢«é’©å–的渔获,会自然生æˆåœ¨æŒ‡å®šç”Ÿæ€ç¾¤ç³»çš„æ°´é¢ä¸Š
@@ -22,6 +21,15 @@ public static void RegisterFish(ModBiome biome, FishableItem item)
value.Add(item);
}
+ ///
+ /// æ³¨å†Œä¸€ç§æ¶²ä½“,在钓鱼时将会模拟原版液体的行为
+ ///
+ /// 图å—çš„ ID
+ public static void RegisterLiquid(int liquid)
+ {
+ LiquidList.Add(liquid);
+ }
+
public List ShouldSpawnFish(Player player)
{
List toSpawn = [];
@@ -32,7 +40,7 @@ public List ShouldSpawnFish(Player player)
foreach (var item in kvp.Value)
{
float chance = Main.rand.NextFloat(1);
- if (chance < item.chance)
+ if (chance < item.Chance)
{
toSpawn.Add(item);
}
diff --git a/Sources/Modules/Yggdrasil/Common/Fish/FishUtils.cs b/Sources/Modules/Yggdrasil/Common/Fish/FishUtils.cs
deleted file mode 100644
index 94a3226d4..000000000
--- a/Sources/Modules/Yggdrasil/Common/Fish/FishUtils.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Everglow.Yggdrasil.Common.Fish;
-
-public static class FishUtils
-{
-}
diff --git a/Sources/Modules/Yggdrasil/Common/Fish/FishableItem.cs b/Sources/Modules/Yggdrasil/Common/Fish/FishableItem.cs
index 6a22cf771..84a136ee1 100644
--- a/Sources/Modules/Yggdrasil/Common/Fish/FishableItem.cs
+++ b/Sources/Modules/Yggdrasil/Common/Fish/FishableItem.cs
@@ -10,11 +10,13 @@ namespace Everglow.Yggdrasil.Common.Fish;
/// 生æˆä¸€ä¸ªå¯ä»¥è¢«é’“鱼的物å“
///
/// ç‰©å“ id
-/// 物å“会在什么液体上生æˆ
+///
+/// 物å“会在什么液体上生æˆï¼ŒåŽŸç‰ˆæ¶²ä½“ä½¿ç”¨ LiquidID,ModLiquid 液体使用 LiquidLoader.LiquidType
+///
/// ç‰©å“æ¯å¸§çš„ç”Ÿæˆæ¦‚率
public class FishableItem(int item, int liquid, float chance)
{
public int Item = item;
public int Liquid = liquid;
- public float chance = chance;
+ public float Chance = chance;
}
diff --git a/Sources/Modules/Yggdrasil/YggdrasilTown/NPCs/NPCSpawnManager.cs b/Sources/Modules/Yggdrasil/Common/NPCSpawnManager.cs
similarity index 97%
rename from Sources/Modules/Yggdrasil/YggdrasilTown/NPCs/NPCSpawnManager.cs
rename to Sources/Modules/Yggdrasil/Common/NPCSpawnManager.cs
index 2d1f6e41c..c3e059654 100644
--- a/Sources/Modules/Yggdrasil/YggdrasilTown/NPCs/NPCSpawnManager.cs
+++ b/Sources/Modules/Yggdrasil/Common/NPCSpawnManager.cs
@@ -1,11 +1,13 @@
using SubworldLibrary;
-namespace Everglow.Yggdrasil.YggdrasilTown.NPCs;
+namespace Everglow.Yggdrasil.Common;
public class NPCSpawnManager : GlobalNPC
{
private static HashSet yggdrasilNPC = new HashSet();
+
public static void RegisterNPC(int type) => yggdrasilNPC.Add(type);
+
public override void EditSpawnPool(IDictionary pool, NPCSpawnInfo spawnInfo)
{
if (!SubworldSystem.IsActive())
@@ -25,7 +27,6 @@ public override void EditSpawnPool(IDictionary pool, NPCSpawnInfo sp
foreach (var pair in dict)
{
pool.Add(pair.Key, pair.Value);
-
}
pool.Add(NPCID.BlueSlime, 0.1f);
pool.Add(NPCID.GreenSlime, 0.1f);
@@ -55,10 +56,8 @@ public override void EditSpawnPool(IDictionary pool, NPCSpawnInfo sp
pool.Add(NPCID.HoppinJack, 0.1f);
}
}
-
-
-
}
+
public override void EditSpawnRate(Player player, ref int spawnRate, ref int maxSpawns)
{
if (SubworldSystem.IsActive())
@@ -77,6 +76,7 @@ public override void EditSpawnRate(Player player, ref int spawnRate, ref int max
}
}
}
+
public static Vector2 FindTheIntersectionOfEllipseAndLine(float a, float b, float c, float d)
{
float a2 = (float)Math.Pow(a, 2);
diff --git a/Sources/Modules/Yggdrasil/Common/YggdrasilBiomeTileCounter.cs b/Sources/Modules/Yggdrasil/Common/YggdrasilBiomeTileCounter.cs
index 3453f08c2..02e49577a 100644
--- a/Sources/Modules/Yggdrasil/Common/YggdrasilBiomeTileCounter.cs
+++ b/Sources/Modules/Yggdrasil/Common/YggdrasilBiomeTileCounter.cs
@@ -1,6 +1,7 @@
using Everglow.Yggdrasil.YggdrasilTown.Tiles;
using Everglow.Yggdrasil.YggdrasilTown.Tiles.LampWood;
using Everglow.Yggdrasil.YggdrasilTown.Tiles.TwilightForest;
+using Everglow.Yggdrasil.YggdrasilTown.Tiles.TwilightForest.RoomScenes;
namespace Everglow.Yggdrasil.Common;
@@ -10,10 +11,14 @@ public class YggdrasilBiomeTileCounter : ModSystem
public int TwilightGrassCount;
public int JellyBallSecretionCount;
+ public int WaterSluiceRoomCount;
+
public override void TileCountsAvailable(ReadOnlySpan tileCounts)
{
DarkForestGrassCount = tileCounts[ModContent.TileType()];
TwilightGrassCount = tileCounts[ModContent.TileType