Player Item Animation - mikrono/tModLoaderWiki_kr_ko GitHub Wiki
Player item animation seems simple at first, but it begs a few questions.
Notably, how does the Clockwork Assault rifle work like it does? Why can't you switch items for a short while after using some weapons?
All of these questions will be answered below.
itemTime, itemAnimation and reuseDelay
In order to keep track of when the player is using an item, the game uses three variables in Player
: itemTime
, itemAnimation
and reuseDelay
.
itemTime
player.itemTime
determines how long the current "use" for the player's held item will last for. When this value reaches zero and player.itemAnimation
hasn't reached zero yet, then the use code for the item will repeat.
Most codes in vanilla, including tile placing, first check if player.itemTime == 0
(among other conditions), then set player.itemTime = player.useTime;
(give or take a call to PlayerHooks.TotalUseTime()
or use speed modifiers such as player.wallSpeed
) if that was true.
After that, the actual "use code" for the item will run and the game will wait until player.itemTime == 0 && player.itemAnimation > 0
is true (among other conditions depending on the item).
Example (item.shoot > 0
code):
if (item.type == 2223)
shoot = 357;
itemTime = PlayerHooks.TotalUseTime(item.useTime, this, item);
Vector2 vector = RotatedRelativePoint(MountedCenter);
bool flag9 = false;
itemAnimation
player.itemAnimation
, in conjunction with player.itemAnimationMax
, is used to determine how far along in the use animation the player is in.
Any item use is wrapped around a check of player.itemAnimation > 0
, so this field is what drives the use.
Noteworthy Cases:
- If the player's held item's
useTime
is equal to itsuseAnimation
, nothing spetacular happens. - If the player's held item's
useTime
is less than itsuseAnimation
, the item use code will be called multiple times during the animation due what was mentioned in the previous sub-section. - If the player's held item's
useTime
is greater than itsuseAnimation
, then the player will be unable to switch items nor use the item again untilplayer.itemTime
has reached zero, which would happen after the use animation finishes.- However, if
player.reuseDelay
is greater than0
whenplayer.itemAnimation
reaches 0 in this case, the leftover timer fromplayer.itemTime
will be overwritten.
- However, if
Example (item.shoot > 0
check):
flag8 = flag8 && ItemLoader.CheckProjOnSwing(this, item);
if (item.shoot > 0 && itemAnimation > 0 && itemTime == 0 && flag8) {
int shoot = item.shoot;
// ...
For reference, this is what ItemLoader.CheckProjOnSwing(Player, Item)
does:
public static bool CheckProjOnSwing(Player player, Item item){
return item.modItem == null || !item.modItem.OnlyShootOnSwing || player.itemAnimation == player.itemAnimationMax - 1;
}
Basically, it makes sure that the player is just starting the item use animation.
Items that use item.useStyle = 5;
bypass the above method call.
reuseDelay
player.reuseDelay
is the intended way to force the player to wait a bit longer after using an item (via item.reuseDelay
).
However, for any items where item.melee
, item.createTile > 0
or item.createWall > 0
is true, this field is ignored.
If item.reuseDelay > 0
is true for the player's held item, the following code is ran just before the check for if the player just clicked the "use item" button (usually Left Mouse):
// Found in Player.ItemCheck(int)
if (itemAnimation == 0 && reuseDelay > 0){
itemAnimation = reuseDelay;
itemTime = reuseDelay;
reuseDelay = 0;
}
Thus, the player has to wait this additional time and an additional item use doesn't occur since player.itemAnimation > 0 && player.itemTime == 0
will never be true after the above code snippet runs.
Other Information
How does the Clockwork Assault rifle work like it does?
The Clockwork Assault Rifle item has the following code in its defaults:
useAnimation = 12;
useTime = 4;
reuseDelay = 14;
Due to useTime
being less than useAnimation
, player.itemTime
will end up looping 12 / 4 = 3
times before forcing the item animation to continue for 14
frames.
Why can't you switch items for a short while after using some weapons?
In Player.Update(int)
, the condition player.itemAnimation == 0 && player.itemTime == 0 && player.reuseDelay == 0
must be true before checking the triggers in PlayerInput.Triggers.Current
for the 10 hotbar slots.
if (PlayerInput.Triggers.Current.Hotbar1) {
selectedItem = 0;
flag7 = true;
}
if (PlayerInput.Triggers.Current.Hotbar2) {
selectedItem = 1;
flag7 = true;
}
if (PlayerInput.Triggers.Current.Hotbar3) {
selectedItem = 2;
flag7 = true;
}
if (PlayerInput.Triggers.Current.Hotbar4) {
selectedItem = 3;
flag7 = true;
}
if (PlayerInput.Triggers.Current.Hotbar5) {
selectedItem = 4;
flag7 = true;
}
if (PlayerInput.Triggers.Current.Hotbar6) {
selectedItem = 5;
flag7 = true;
}
if (PlayerInput.Triggers.Current.Hotbar7) {
selectedItem = 6;
flag7 = true;
}
if (PlayerInput.Triggers.Current.Hotbar8) {
selectedItem = 7;
flag7 = true;
}
if (PlayerInput.Triggers.Current.Hotbar9) {
selectedItem = 8;
flag7 = true;
}
if (PlayerInput.Triggers.Current.Hotbar10) {
selectedItem = 9;
flag7 = true;
}
On the other hand, if that condition was false, the game instead checks the number keys on the main keyboard (D0
through D9
) specifically instead of the triggers set.
if (Main.keyState.IsKeyDown(D1)) {
selectedItem = 0;
flag10 = true;
}
if (Main.keyState.IsKeyDown(D2)) {
selectedItem = 1;
flag10 = true;
}
if (Main.keyState.IsKeyDown(D3)) {
selectedItem = 2;
flag10 = true;
}
if (Main.keyState.IsKeyDown(D4)) {
selectedItem = 3;
flag10 = true;
}
if (Main.keyState.IsKeyDown(D5)) {
selectedItem = 4;
flag10 = true;
}
if (Main.keyState.IsKeyDown(D6)) {
selectedItem = 5;
flag10 = true;
}
if (Main.keyState.IsKeyDown(D7)) {
selectedItem = 6;
flag10 = true;
}
if (Main.keyState.IsKeyDown(D8)) {
selectedItem = 7;
flag10 = true;
}
if (Main.keyState.IsKeyDown(D9)) {
selectedItem = 8;
flag10 = true;
}
if (Main.keyState.IsKeyDown(D0)) {
selectedItem = 9;
flag10 = true;
}