How to implement every possible Yanfly Tips & Tricks effect in MZ with VisuStella plugins

ATT_Turan

Forewarner of the Black Wind
Regular
Joined
Jul 2, 2014
Messages
12,595
Reaction score
11,070
First Language
English
Primarily Uses
RMMV
The "Jump" spell doesn't seem to work for me, my character stays stuck in the air and never falls...
(After 2 turns he can act again but does not come back)
And the target is affected by the jump state, that doesn't seem normal to me x)
Can you post screenshots of your skills and action sequence? It sounds like you copied something incorrectly - the entire enemy troop should have the "Jump Target Redirect" state (although hopefully you can't see it), and your off-screen actor should have the "Jump" state.

Perhaps you accidentally put Add State to "current target" instead of "user".
 

Onox

Villager
Member
Joined
Apr 17, 2020
Messages
10
Reaction score
3
First Language
French
Primarily Uses
RMMZ
I can't import my screenshots with the "insert image" function...
"Oops! We ran into some problems."
I had indeed forgotten to create a "Jump Target Redirect" state.
Now the enemies are no longer affected by the "Jump" state but my character still does not want to complete his attack and remains stuck in the air T-T

Thanks a lot for your help !

 
Last edited:

ATT_Turan

Forewarner of the Black Wind
Regular
Joined
Jul 2, 2014
Messages
12,595
Reaction score
11,070
First Language
English
Primarily Uses
RMMV
Now the enemies are no longer affected by the "Jump" state but my character still does not want to complete his attack and remains stuck in the air T-T
Well, without screenshots I can't correct you specifically, but just double check again that you've copied the code correctly.

The part that makes your actor come back down is in the JS Pre-Regenerate tag which goes in the Jump state. So if your actor is now correctly receiving the Jump state, and you have correctly copied that code, after two turns have passed he'll execute the Land skill.

So make sure that the action sequence for the Land skill is copied correctly and make sure that in that Pre-Regenerate tag the line that says const skill = 277 correctly reflects the ID of your Land skill. No leading zeros ever.

Basically...just go through the copying and instructions again.
 

Onox

Villager
Member
Joined
Apr 17, 2020
Messages
10
Reaction score
3
First Language
French
Primarily Uses
RMMZ
Well, without screenshots I can't correct you specifically, but just double check again that you've copied the code correctly.

The part that makes your actor come back down is in the JS Pre-Regenerate tag which goes in the Jump state. So if your actor is now correctly receiving the Jump state, and you have correctly copied that code, after two turns have passed he'll execute the Land skill.

So make sure that the action sequence for the Land skill is copied correctly and make sure that in that Pre-Regenerate tag the line that says const skill = 277 correctly reflects the ID of your Land skill. No leading zeros ever.

Basically...just go through the copying and instructions again.

Yes sorry I edited my original message through an external host
I use the visustella OTB system
Is it possible that a bad interaction is causing this problem?
 
Last edited:

JadeTheurgist

Regular
Regular
Joined
Apr 19, 2020
Messages
37
Reaction score
4
First Language
English
Primarily Uses
RMMZ
Has anyone been having trouble with getting Dualcast to work for them? I copied the code into a state, but none of my magic skils are triggering it. At first I thought it might somehow be because I was applying the state as a passive, but testing with it applied by a skill like in the original had the same result.

Edit: So I have made an interesting discovery. The current battle system you are using will affect how Dualcast works. Oringinally while testing this, I was using the OTB system and nothing happened, but swapping to the STB system gives the extra cast, BUT LETS YOU PICK THE SKILL. I say skill, because it doesn't seem limited to just magic skills in this extra selection. I haven't tested this with other battle systems, but I'm very curious to see how others react.
 
Last edited:

FrigidGaze

Regular
Regular
Joined
May 12, 2022
Messages
221
Reaction score
307
First Language
English
Primarily Uses
RMMZ
Has anyone been having trouble with getting Dualcast to work for them? I copied the code into a state, but none of my magic skils are triggering it. At first I thought it might somehow be because I was applying the state as a passive, but testing with it applied by a skill like in the original had the same result.

Edit: So I have made an interesting discovery. The current battle system you are using will affect how Dualcast works. Oringinally while testing this, I was using the OTB system and nothing happened, but swapping to the STB system gives the extra cast, BUT LETS YOU PICK THE SKILL. I say skill, because it doesn't seem limited to just magic skills in this extra selection. I haven't tested this with other battle systems, but I'm very curious to see how others react.
Hiya!

Having implemented dualcast into my own project recently, I ran into the same dilemma as you while using the STB system--where it was giving me a free action entirely instead of duplicating the skill.

Looking at the Yanfly page for the original skill, it has a small extra bit to it that mentions to change how the action is forced if you've using anything other than the default battle system via 'BattleManager.queueForceAction' since I assume there's been modifications to how actions and turns are handled in the plugins.

This force action command seems to have been changed up slightly in MZ, so I had to experiment and search around, but I've got it working my end now on the STB system!

Code:
<JS Post-Start Action>
  if (!$gameTemp._chainAction) {
    $gameTemp._chainAction = user.currentAction();
  } else {
    delete $gameTemp._chainAction;
  }
</JS Post-Start Action>

<JS Pre-End Action>
  if ($gameTemp._chainAction) {
    const action = $gameTemp._chainAction;
    if (action && action.isSkill() && action.isMagical()) {
      const skill = action.item();
      if (user.canPaySkillCost(skill)) {
        user.forceAction(skill.id, -2);
      }
    }
  }
</JS Pre-End Action>

<JS On Erase State>
  delete $gameTemp._chainAction;
</JS On Erase State>

Essentially, I replaced 'user.setAction(0, action);' with 'user.forceAction(skill.id, -2);' as per the Yanfly instructions with the MZ specific adjustments.
 

tinkie99

Regular
Regular
Joined
Feb 17, 2021
Messages
48
Reaction score
8
First Language
Dutch
Primarily Uses
RMMZ
So will the rod of ages reset to it's starting stats in the next battle or how does it work
 

ATT_Turan

Forewarner of the Black Wind
Regular
Joined
Jul 2, 2014
Messages
12,595
Reaction score
11,070
First Language
English
Primarily Uses
RMMV
So will the rod of ages reset to it's starting stats
Correct - you can see the parameters are based on the turn count, and each battle starts its turn count at 0, so it starts at its base parameters again.
 

tinkie99

Regular
Regular
Joined
Feb 17, 2021
Messages
48
Reaction score
8
First Language
Dutch
Primarily Uses
RMMZ
Correct - you can see the parameters are based on the turn count, and each battle starts its turn count at 0, so it starts at its base parameters again.
So with how the code is, there's no limit, right? Rod of ages will scale as long as the battle continues basically?
 

ATT_Turan

Forewarner of the Black Wind
Regular
Joined
Jul 2, 2014
Messages
12,595
Reaction score
11,070
First Language
English
Primarily Uses
RMMV
So with how the code is, there's no limit, right? Rod of ages will scale as long as the battle continues basically?
No. The fourth line says the multiplier can only be between 0 to 10. So once you've had 20 turns of battle the rod is at max power.
 

tinkie99

Regular
Regular
Joined
Feb 17, 2021
Messages
48
Reaction score
8
First Language
Dutch
Primarily Uses
RMMZ
No. The fourth line says the multiplier can only be between 0 to 10. So once you've had 20 turns of battle the rod is at max power.
Oh, I see, thanks for clearing that up!
 

Dark_Ansem

Regular
Regular
Joined
Jun 16, 2020
Messages
652
Reaction score
162
First Language
English
Primarily Uses
RMMZ
So, this may be a bit of a tall order but the newest Visustella update added selection control to its Battle Core plugin via Notetag. Could this be enough to actually implement the plugins that weren't possible before due to the lack of selection control mechanics?
 

Renkai141

Pain make sme a believer
Regular
Joined
Oct 31, 2018
Messages
33
Reaction score
5
First Language
Spanish & EN
Primarily Uses
RMMZ
Q : For Battle statistics, how would you display said information?
 

ATT_Turan

Forewarner of the Black Wind
Regular
Joined
Jul 2, 2014
Messages
12,595
Reaction score
11,070
First Language
English
Primarily Uses
RMMV
Q : For Battle statistics, how would you display said information?
Not to be unhelpful, but...it depends on what you're trying to do :stickytongue:

You need to know a bit about the ways to access an actor.

If you want to do it in an event, you could do:
Control Variables -> 3 -> Script -> $gameParty.members()[0]._killCount
Show Text -> The first party member's kill count is \V[3]

Or you could pull it from actor ID 5 with $gameActors.actor(5)._killCount

If you're making a custom scene as a part of your menu to display the statistics, one might presume you know how to refer to the actors within it.
 

DarthKai

Regular
Regular
Joined
Jan 11, 2023
Messages
76
Reaction score
14
First Language
English
Primarily Uses
Other
This works the same way as the original but needs <JS Pre-Apply> instead of <Before Eval>.

JavaScript:
<HRG Rate: 0%>

NOTE: You will need to add an if statement
to all DoT effects which use notetags in
order for this to work properly

For example, the Toxic effect won't be affected because it doesn't use the native regeneration functionality. You could incorporate HRG into such effects rather than using branching logic if you had a lot of them in your game.

JavaScript:
<JS Pre-Apply>
  const stateId = 69;
  if (target.isStateAffected(stateId)) {
    target.removeState(stateId);
  } else {
    target.addState(stateId);
  }
</JS Pre-Apply>

Replace 69 with the ID of your Mending state, which will have the following code:

JavaScript:
<JS Pre-Regenerate>
  const mpUpkeep = 5;
  if (origin.isAlive() && origin.mp >= mpUpkeep) {
    origin.gainMp(-mpUpkeep);
    origin.startDamagePopup();
    const regen = Math.floor(origin.mdf / 2);
    user.gainHp(regen);
    user.startDamagePopup();
  } else {
    origin.removeState(state.id);
  }
</JS Pre-Regenerate>

Just needs a <Custom Action Sequence>. The common event should look like this:
◆If:Script:BattleManager._action.subject().getAttackMotion().type !== 2
◆Plugin Command:VisuMZ_1_BattleCore, BTLOG: Display Action
◆Plugin Command:VisuMZ_1_BattleCore, MOVE: Move To Target(s)
: :Targets (Moving) = ["user"]
: :Targets (Destination) = ["all targets"]
: :Target Location = front base
: :Melee Distance = 24
: :Offset Adjustment = horz
: :Offset: X = 0
: :Offset: Y = 0
: :Duration = 20
: :Face Destination? = true
: :Movement Easing = Linear
: :Movement Motion = walk
: :Wait For Movement? = false

:Else
◆Plugin Command:VisuMZ_1_BattleCore, ACSET: Setup Action Set
: :Display Action = true
: :Immortal: On = true
: :Battle Step = true
: :Wait For Movement = true
: :Cast Animation = true
: :Wait For Animation = false

:End
◆Plugin Command:VisuMZ_1_BattleCore, MOTION: Motion Type
: :Targets = ["user"]
: :Motion Type = wait
: :Show Weapon? = true
◆Plugin Command:VisuMZ_1_BattleCore, MOVE: Wait For Movement
◆Plugin Command:VisuMZ_1_BattleCore, MOVE: Face Target(s)
: :Targets (facing) = ["user"]
: :Targets (destination) = ["current target"]
: :Face Away From? = false
◆Plugin Command:VisuMZ_1_BattleCore, MOTION: Motion Type
: :Targets = ["user"]
: :Motion Type = attack
: :Show Weapon? = true
◆Wait:10 frames
◆Plugin Command:VisuMZ_1_BattleCore, ANIM: Attack Animation
: :Targets = ["all targets"]
: :Mirror Animation = false
: :Wait For Animation? = true
◆If:Script:BattleManager._action.subject().hasWeapon($dataWeapons[1])
◆Plugin Command:VisuMZ_1_BattleCore, ELE: Force Elements
: :Elements = ["2"]
◆Plugin Command:VisuMZ_1_BattleCore, ANIM: Show Animation
: :Targets = ["all targets"]
: :Animation ID = 8
: :Mirror Animation = false
: :Wait For Animation? = false

:Else
◆If:Script:BattleManager._action.subject().hasWeapon($dataWeapons[2])
◆Plugin Command:VisuMZ_1_BattleCore, ELE: Force Elements
: :Elements = ["3"]
◆Plugin Command:VisuMZ_1_BattleCore, ANIM: Show Animation
: :Targets = ["all targets"]
: :Animation ID = 9
: :Mirror Animation = false
: :Wait For Animation? = false

:End

:End
◆Plugin Command:VisuMZ_1_BattleCore, MECH: Action Effect
: :Targets = ["all targets"]
◆Plugin Command:VisuMZ_1_BattleCore, ELE: Clear Element Changes
◆Plugin Command:VisuMZ_1_BattleCore, ANIM: Wait For Animation
◆Plugin Command:VisuMZ_1_BattleCore, ACSET: Finish Action
: :Immortal: Off = true
: :Wait For New Line = true
: :Wait For Effects = true
: :Clear Battle Log = true
: :Home Reset = true
: :Wait For Movement = true

Modify the ID of the weapon(s) being checked for and IDs of the associated elements according to your needs.

JavaScript:
<JS Pre-Apply>
  if (!this._sharedLifeRate) {
    this._sharedLifeRate = 0;
    const members = this.friendsUnit().aliveMembers();
    for (let i = 0; i < members.length; ++i) {
      const member = members[i];
      this._sharedLifeRate += member.hpRate();
    }
    this._sharedLifeRate /= members.length;
    this._sharedLifeRate += 0.15;
  }
</JS Pre-Apply>

<JS Post-Apply>
  if (target.isAlive()) {
    const targetHp = Math.floor(this._sharedLifeRate * target.mhp);
    const difference = targetHp - target.hp;
    if (difference > 0) {
      $gameTemp.requestAnimation([target], 41);
    } else if (difference < 0) {
      $gameTemp.requestAnimation([target], 54);
    }
    if (difference !== 0) {
      target.gainHp(difference);
      target.startDamagePopup();
    }
  }
</JS Post-Apply>

JavaScript:
<Reapply Rules: Ignore>

<JS On Add State>
  target._promisedDamage ??= 0;
</JS On Add State>

<JS Pre-Damage As Target>
  if (this.isHpEffect()) {
    target._promisedDamage ??= 0;
    if (value > 0) {
      target._promisedDamage += value;
    } else {
      target._promisedDamage += value * 2;
    }
    value = 0;
  }
</JS Pre-Damage As Target>

<JS On Erase State>
  target._promisedDamage ??= 0;
  if (target._promisedDamage > 0) {
    $gameTemp.requestAnimation([target], 11);
  } else {
    $gameTemp.requestAnimation([target], 41);
  }
  target.gainHp(-target._promisedDamage);
  delete target._promisedDamage;
  target.startDamagePopup();
</JS On Erase State>

JavaScript:
<JS Pre-Start Action>
  const paralyzeRate = 0.75;
  if (Math.random() < paralyzeRate) {
    $gameTemp.requestAnimation([user], 64);
    if (user.currentAction()) {
      user.useItem(user.currentAction().item());
    }
    this.setSkill(286);
    const logWindow = SceneManager._scene._logWindow;
    if ($dataStates[71].message3) {
      const msg = '<CENTER>' + user.name() + $dataStates[71].message3;
      logWindow.addText(msg);
      logWindow.refresh();
    }
  }
</JS Pre-Start Action>

This will need a "Paralyzed" skill with scope set to the user which does nothing, which in my project is 286. Adjust the ID as needed. Replace 71 with the ID of the Paralyze state.

Just needs a <Custom Action Sequence>. The common event should look like this:
◆If:Script:BattleManager._action.subject().getAttackMotion().type !== 2
◆Plugin Command:VisuMZ_1_BattleCore, BTLOG: Display Action
◆Plugin Command:VisuMZ_1_BattleCore, MOVE: Move To Target(s)
: :Targets (Moving) = ["user"]
: :Targets (Destination) = ["all targets"]
: :Target Location = front base
: :Melee Distance = 24
: :Offset Adjustment = horz
: :Offset: X = 0
: :Offset: Y = 0
: :Duration = 20
: :Face Destination? = true
: :Movement Easing = Linear
: :Movement Motion = walk
: :Wait For Movement? = false

:Else
◆Plugin Command:VisuMZ_1_BattleCore, ACSET: Setup Action Set
: :Display Action = true
: :Immortal: On = true
: :Battle Step = true
: :Wait For Movement = true
: :Cast Animation = true
: :Wait For Animation = false

:End
◆Plugin Command:VisuMZ_1_BattleCore, MOTION: Motion Type
: :Targets = ["user"]
: :Motion Type = wait
: :Show Weapon? = true
◆Plugin Command:VisuMZ_1_BattleCore, MOVE: Wait For Movement
◆Plugin Command:VisuMZ_1_BattleCore, MOVE: Face Target(s)
: :Targets (facing) = ["user"]
: :Targets (destination) = ["current target"]
: :Face Away From? = false
◆Plugin Command:VisuMZ_1_BattleCore, MOTION: Motion Type
: :Targets = ["user"]
: :Motion Type = attack
: :Show Weapon? = true
◆Wait:10 frames
◆Plugin Command:VisuMZ_1_BattleCore, ANIM: Attack Animation
: :Targets = ["all targets"]
: :Mirror Animation = false
: :Wait For Animation? = true
◆Script:BattleManager._action._targetHp = BattleManager._action.subject().opponentsUnit().members()[BattleManager._action._targetIndex].hp
◆Plugin Command:VisuMZ_1_BattleCore, MECH: Action Effect
: :Targets = ["all targets"]
◆If:Script:BattleManager._action.subject().opponentsUnit().members()[BattleManager._action._targetIndex].hp === BattleManager._action._targetHp
◆Plugin Command:VisuMZ_1_BattleCore, MECH: Add Buff/Debuff
: :Targets = ["user"]
: :Buff Parameters = []
: :Debuff Parameters = ["AGI"]
: :Turns = 5
◆Plugin Command:VisuMZ_1_BattleCore, ANIM: Show Animation
: :Targets = ["user"]
: :Animation ID = 54
: :Mirror Animation = false
: :Wait For Animation? = false
◆Plugin Command:VisuMZ_1_BattleCore, MOTION: Motion Type
: :Targets = ["user"]
: :Motion Type = dead
: :Show Weapon? = true
◆Plugin Command:VisuMZ_1_BattleCore, ANIM: Wait For Animation

:End
◆Script:delete BattleManager._action._targetHp
◆Plugin Command:VisuMZ_1_BattleCore, ACSET: Finish Action
: :Immortal: Off = true
: :Wait For New Line = true
: :Wait For Effects = true
: :Clear Battle Log = true
: :Home Reset = true
: :Wait For Movement = true

All states involved in this need a <No Death Clear> tag. The code that goes into the death state is the same as in the original, though I used "let" and "const" instead of "var".

JavaScript:
<JS Post-Damage As User>
  if (this.isHpEffect() && value > 0) {
    const actionElements = this.elements();
    const matchingElements = [2, 3, 4, 5, 6, 7, 8, 9];
    let condition = false;
    for (let i = 0; i < actionElements.length; ++i) {
      if (matchingElements.contains(actionElements[i])) {
        condition = true;
        break;
      }
    }
    if (condition) {
      const exposedState = 89;
      target.addState(exposedState);
    }
  }
</JS Post-Damage As User>

Modify matchingElements according to your own element types, and change 89 to the ID of your Expose Weakness state. That state should have the following code:

JavaScript:
<JS On Add State>
  target._exposedWeakness ??= 0;
  target._exposedWeakness = Math.min(4, target._exposedWeakness + 1);
  const counterText = "+" + (target._exposedWeakness * 5) + "%";
  target.setStateDisplay(state.id, counterText);
</JS On Add State>

<JS On Remove State>
  delete target._exposedWeakness;
  target.clearStateDisplay(89);
</JS On Remove State>

<JS Pre-Damage As Target>
  if (this.isHpEffect() && value > 0) {
    target._exposedWeakness = target._exposedWeakness || 0;
    let multiplier = 1;
    multiplier += target._exposedWeakness * 0.05;
    value *= multiplier;
    value = Math.ceil(value);
  }
</JS Pre-Damage As Target>

JavaScript:
<JS Pre-Damage As User>
  if (this.isMagical() && value !== 0) {
    value = Math.ceil(value * 1.5);
  }
</JS Pre-Damage As User>

This effect requires the tier 2 STB battle system for the instant tag.

JavaScript:
<Custom Action Sequence>
<STB Instant>

Action sequence for instant skills:
◆Plugin Command:VisuMZ_1_BattleCore, ACSET: Setup Action Set
: :Display Action = true
: :Immortal: On = true
: :Battle Step = true
: :Wait For Movement = true
: :Cast Animation = false
: :Wait For Animation = false
◆Plugin Command:VisuMZ_1_BattleCore, ACSET: All Targets Action Set
: :Dual/Multi Wield? = false
: :Perform Action = true
: :Wait Count = Sprite_Battler._motionSpeed
: :Action Animation = true
: :Wait For Animation = false
: :Action Effect = true
: :Immortal: Off = false
◆Plugin Command:VisuMZ_1_BattleCore, ACSET: Finish Action
: :Immortal: Off = true
: :Wait For New Line = true
: :Wait For Effects = true
: :Clear Battle Log = true
: :Home Reset = true
: :Wait For Movement = true

The action sequence for this is too long and specific to be worth transcribing, but if anyone really wants to see how it's done in VisuStella plugins PM me and I'll paste the common event.

JavaScript:
<JS Post-Damage As Target>
  if (target.result().hpDamage > 0) {
    let elements = this.elements();
    while (elements.length > 0) {
      const element = elements.shift();
      if (element >= 2 && element <= 9) {
        target.addState(element + 89);
        $gameTemp.requestAnimation([target], 53);
      }
    }
  }
</JS Post-Damage As Target>

The way I've set this up requires that all the elemental guard states and element types are in sequence. Change 89 to the ID of your first guard state minus the ID of the first element. If you haven't got yours in sequence, you'll need to modify this slightly.

JavaScript:
<JS Post-Apply>
  if (user.isActor() && target.isEnemy() && (target.isDead() || target.hp <= 0)) {
    const id = target.enemyId();
    const pool = [];
    pool.push($dataItems[7]);
    pool.push($dataItems[8]);
    pool.push($dataItems[9]);
    if (id === 1) {
      pool.push($dataWeapons[1]);
    } else if (id === 2) {
      pool.push($dataWeapons[2]);
      pool.push($dataWeapons[3]);
    } else if (id === 3) {
      pool.push($dataArmors[2]);
      pool.push($dataArmors[3]);
      pool.push($dataArmors[4]);
    }
    const item = pool[Math.randomInt(pool.length)];
    if (item) {
      $gameTemp.requestAnimation([target], 2);
      target.removeImmortal();
      SoundManager.playShop();
      $gameParty.gainItem(item, 1);
      const msg = '<CENTER>' + user.name() + ' acquired \\i[' + item.iconIndex + ']' + item.name + ' from ' + target.name() + '!';
      const logWindow = SceneManager._scene._logWindow;
      logWindow.addStealText(msg);
    }
  }
</JS Post-Apply>

Modify the pool array as necessary for your game.

JavaScript:
<JS On Add State>
  target._earthShieldHeal = Math.floor(origin.mat * 0.5);
  target.setStateDisplay(state.id, 9);
</JS On Add State>

<JS On Erase State>
  delete target._earthShieldHeal;
  target.clearStateDisplay(state.id);
</JS On Erase State>

<JS Pre-Damage As Target>
  if (this.isHpEffect() && value < 0) {
    value = Math.floor(value * 1.2);
    target.setStateDisplay(state.id, target.getStateDisplay(99) - 1);
    if (target.getStateDisplay(state.id) <= 0) {
      target.removeState(state.id);
    }
  }
</JS Pre-Damage As Target>

<JS Post-Apply As Target>
  if (target.isAlive() && target.result().hpDamage > 0) {
    const hpHealed = target._earthShieldHeal || 0;
    target.startDamagePopup();
    target.gainHp(hpHealed);
    target.startDamagePopup();
    target.setStateDisplay(state.id, target.getStateDisplay(99) - 1);
    if (target.getStateDisplay(state.id) <= 0) {
      target.removeState(state.id);
    }
  }
</JS Post-Apply As Target>

JavaScript:
<JS Pre-Start Battle>
  user._criticalProtect = false;
</JS Pre-Start Battle>

<JS Post-End Battle>
  user._criticalProtect = false;
</JS Post-End Battle>

<JS Post-Damage As Target>
  const crisis = 0.25;
  if ($gameParty.inBattle() && target.isAlive() && target.hpRate() <= crisis && !target._criticalProtect) {
    target._criticalProtect = true;
    target._criticalProtectTurns = 5;
    const turns = 5;
    target.addBuff(3, turns);
    $gameTemp.requestAnimation([target], 53);
  }
</JS Post-Damage As Target>

<JS Post-End Turn>
  if (target._criticalProtectTurns) {
    target._criticalProtectTurns--;
    if (target._criticalProtectTurns <= 0) {
      delete target._criticalProtectTurns;
      target._criticalProtect = false;
    }
  }
</JS Post-End Turn>

JavaScript:
<JS Pre-Apply>
  BattleManager.allBattleMembers().forEach(member => member.isStateAffected(102) ? member.removeState(102) : null);
</JS Pre-Apply>

The skill should have an effect to add the "Cyclone Bridge" state. Replace 102 with the ID of your Cyclone state proper. Cyclone Bridge should have the following code:

JavaScript:
<JS On Add State>
  target._cycloneTimes ??= 0;
  const turns = Math.max(5 - target._cycloneTimes * 2, 1);
  target.addState(102);
  target.setStateTurns(102, turns);
  target._cycloneTimes++;
</JS On Add State>

<JS On Erase State>
  delete target_cycloneTimes;
</JS On Erase State>

Again, replace 102 with the ID of your Cyclone state.

JavaScript:
<JS Pre-Apply>
  if (user.isActor()) {
    const allowed = [];
    allowed.push(1, 2, 3, 4);
    const skills = target.skills();
    for (let i = 0; i < skills.length; ++i) {
      const skill = skills[i];
      if (skill && allowed.contains(skill.stypeId) && !user.isLearnedSkill(skill.id)) {
        user.learnSkill(skill.id);
        const text = '<CENTER>' + user.name() + ' has learned \\i[' + skill.iconIndex + ']' + skill.name + ' from ' + target.name() + '!';
        const logWindow = SceneManager._scene._logWindow;
        logWindow._lines.push(text);
        $gameTemp.requestAnimation([user], 119);
      }
    }
  }
</JS Pre-Apply>

Modify the skill type IDs in the allowed array as needed.

JavaScript:
<JS Passive Condition>
  if ($gameParty.inBattle()) {
    condition = user.tp >= 80;
  } else {
    condition = false;
  }
</JS Passive Condition>

Add whatever buffs you wish to the state traits.

JavaScript:
<JS Passive Condition>
  if ($gameParty.inBattle()) {
    user._trance ??= false;
    condition = user._trance || user.tp === user.maxTp();
  } else {
    condition = false;
  }
  if (condition) {
    if (!user._trance) {
      $gameTemp.requestAnimation([user], 120);
    }
    user._trance = true;
  }
</JS Passive Condition>

<JS Pre-Regenerate>
  const tp = 10;
  user.gainTp(-tp);
  if (user.tp === 0) {
    user._trance = false;
  }
</JS Pre-Regenerate>

The setup of the Combo Attack skill should just add the Combo state, which should have the following code:

JavaScript:
<JS On Add State>
  user._comboStacks ??= 0;
  const stacks = user._comboStacks.clamp(0, 10);
  user.setStateDisplay(state.id, 'x' + stacks);
</JS On Add State>

<JS On Erase State>
  user._comboStacks = 0;
  user.setStateDisplay(state.id, 'x' + stacks);
</JS On Erase State>

<JS Pre-Damage As User>
  if (this.isPhysical() && value > 0 && !this.item().name.match('Combo')) {
    user._comboStacks ??= 0;
    let stacks = user._comboStacks.clamp(0, 10);
    const rate = 1 + stacks * 0.1;
    value = Math.ceil(value * rate);
    stacks++;
    stacks = stacks.clamp(0, 10);
    user.setStateDisplay(state.id, 'x' + stacks);
    user._comboStacks = stacks;
  }
</JS Pre-Damage As User>

Skills that use combo points should be set up similarly to this:

JavaScript:
<Custom Cost Text>
  2\i[160]
</Custom Cost Text>

<JS Skill Enable>
  user._comboStacks ??= 0;
  enabled = user._comboStacks >= 2;
</JS Skill Enable>

<JS Pre-start Action>
  user._comboStacks ??= 0;
  let stacks = user._comboStacks;
  stacks -= 2;
  stacks = stacks.clamp(0, 10);
  const comboStateId = 105;
  user.setStateDisplay(comboStateId, 'x' + stacks);
  user._comboStacks = stacks;
</JS Pre-start Action>

Replace 2 with whatever the combo cost is and 105 with the ID of your Combo state.

This requires the tier 3 Auto Skill Triggers plugin.

The state code should be:
JavaScript:
<JS Post-Damage As Target>
  if (value > 0) {
    target._tookDamage = true;
  }
</JS Post-Damage As Target>

<JS Post-End Action>
  target._tookDamage = false;
</JS Post-End Action>

And the skill code should be:

JavaScript:
<Auto Trigger: Certain Hit Enemy>
<Auto Trigger: Physical Enemy>
<Auto Trigger: Magical Enemy>
<Auto Trigger: Item Enemy>

<JS Skill Visible>
  visible = false;
</JS Skill Visible>

<JS Skill Enable>
  enabled = false;
  if (user.isActor()) {
    const potions = [];
    potions.push(7, 8, 9);
    for (let i = 0; i < potions.length; ++i) {
      const id = potions[i];
      if ($gameParty.numItems($dataItems[id]) > 0) {
        enabled = true;
        break;
      }
    }
  } else {
    enabled = true;
  }
</JS Skill Enable>

<JS Pre-Apply>
  if (target._tookDamage) {
    const potions = [];
    potions.push(7, 8, 9);
    for (let i = 0; i < potions.length; ++i) {
      const id = potions[i];
      if ($gameParty.numItems($dataItems[id]) > 0) {
        const item = $dataItems[id];
        if (user.isActor()) {
          $gameParty.loseItem(item, 1);
        }
        this.setItem(id);
        const text = '<CENTER>' + user.name() + ' uses \\i[' + item.iconIndex + ']' + item.name + '!';
        const logWindow = SceneManager._scene._logWindow;
        logWindow._lines.push(text);
        break;
      }
    }
  }
</JS Pre-Apply>

<Custom Action Sequence>

The action sequence is just
◆If:Script:BattleManager._action.subject()._tookDamage
◆Plugin Command:VisuMZ_1_BattleCore, ACSET: Setup Action Set
: :Display Action = true
: :Immortal: On = true
: :Battle Step = true
: :Wait For Movement = true
: :Cast Animation = false
: :Wait For Animation = false
◆Plugin Command:VisuMZ_1_BattleCore, ACSET: All Targets Action Set
: :Dual/Multi Wield? = false
: :Perform Action = true
: :Wait Count = Sprite_Battler._motionSpeed
: :Action Animation = true
: :Wait For Animation = false
: :Action Effect = true
: :Immortal: Off = false
◆Plugin Command:VisuMZ_1_BattleCore, ACSET: Finish Action
: :Immortal: Off = true
: :Wait For New Line = true
: :Wait For Effects = true
: :Clear Battle Log = true
: :Home Reset = true
: :Wait For Movement = true

:End

Note that the state needs the "Add Skill: Auto Potion" trait for this to work. Replace 7, 8, 9 with the IDs of the potions you want to use with the effect, in the order they should be prioritised.

If you want to limit the effect as per the original T&T, you'll also need the tier 3 Limited Skill Uses plugin. Add a <Limited Uses: x> tag to the Auto Potion skill.

JavaScript:
<JS Post-Start Action>
  if (!$gameTemp._chainAction) {
    $gameTemp._chainAction = user.currentAction();
  } else {
    delete $gameTemp._chainAction;
  }
</JS Post-Start Action>

<JS Pre-End Action>
  if ($gameTemp._chainAction) {
    const action = $gameTemp._chainAction;
    if (action && action.isSkill() && action.isMagical()) {
      const skill = action.item();
      if (user.canPaySkillCost(skill)) {
        user.setAction(0, action);
      }
    }
  }
</JS Pre-End Action>

<JS On Erase State>
  delete $gameTemp._chainAction;
</JS On Erase State>

The Living Dead state itself just needs a <No Death Clear> tag. The Walking Dead state's code is:

JavaScript:
<JS Pre-Regenerate>
  if (target.isStateAffected(state.id)) {
    if (target.hp <= 0) {
      target.setHp(1);
    }
  }
</JS Pre-Regenerate>

<JS On Add State>
  target._walkingDeadHp = target.mhp;
  target._walkingDeadFailed = false;
  $gameTemp.requestAnimation([target], 65);
  target.setStateDisplay(state.id, target._walkingDeadHp);
</JS On Add State>

<JS On Erase State>
  target._walkingDeadHp ??= target.mhp;
  if (target._walkingDeadHp > 0) {
    target._walkingDeadFailed = true;
    target.setHp(0);
  }
</JS On Erase State>

<JS Post-Damage As Target>
  target._walkingDeadHp ??= target.mhp;
  if (value < 0) {
    target._walkingDeadHp += value;
    user.setStateDisplay(state.id, Math.max(0, target._walkingDeadHp));
  }
  if (target.hp <= 0) {
    target.setHp(1);
  }
</JS Post-Damage As Target>

And in the Death state:

JavaScript:
<JS On Add State>
  if (target.isStateAffected(108) && !target._walkingDeadFailed) {
    target.removeState(1);
    target.removeState(108);
    target.addState(109);
    user.setHp(1);
  }
</JS On Add State>

Replace 108 with the ID of the Living Dead state, and 109 with the ID of the Walking Dead state.

This effect can't be replicated due to not having the functionality of Selection Control.

The state setup is the same as in the original, as there's no code involved. In any skill which you want Blood Magic to affect, you'd put the following:

JavaScript:
<JS MP Cost>
  if (user.isStateAffected(110)) {
    cost = 0;
  }
</JS MP Cost>
<JS HP Cost>
  if (user.isStateAffected(110)) {
    cost = skill.mpCost * 2;
  }
</JS HP Cost>

JavaScript:
<JS On Add State>
  target._healingFateDamage = 0;
</JS On Add State>

<JS On Erase State>
  delete target._healingFateDamage;
</JS On Erase State>

<JS Post-Damage As Target>
  if (this.isHpEffect() && value > 0) {
    target._healingFateDamage += value;
    if (target._healingFateDamage >= target.mhp * 0.2) {
      target.removeState(state.id);
      const members = origin.friendsUnit().aliveMembers();
      const hpHealed = origin.mdf * 2;
      for (let i = 0; i < members.length; ++i) {
        const member = members[i];
        if (member) {
          member.gainHp(hpHealed);
          $gameTemp.requestAnimation([member], 46);
          member.startDamagePopup();
        }
      }
    }
  }
</JS Post-Damage As Target>

The skill code should be:

JavaScript:
<JS Pre-Damage>
  target._currentHp = target.hp;
</JS Pre-Damage>

<JS Post-Damage>
  if (target._currentHp && target.hp <= 0) {
    const damage = value - target._currentHp;
    if (damage > 0) {
      const overkillStateId = 112;
      user.addState(overkillStateId);
      user._overkillBonus = damage;
      $gameTemp.requestAnimation([user], 51);
    }
  }
  delete target._currentHp;
</JS Post-Damage>

Replace 112 with the ID of your Overkill state, which should have the following code:

JavaScript:
<JS Pre-Damage As User>
  if (this.isHpEffect() && value > 0) {
    user._overkillBonus ??= 0;
    value += Math.min(value * 5, user._overkillBonus);
    $gameTemp.requestAnimation([target], 13);
  }
</JS Pre-Damage As User>

JavaScript:
<JS Pre-Start Action>
  user._reverenceMp = user.mp;
</JS Pre-Start Action>

<JS Pre-Apply As User>
  if (user._reverenceMp) {
    const difference = user._reverenceMp - user.mp;
    if (difference > 0) {
      const hp = Math.ceil(difference * 20);
      user.gainHp(hp);
      user.startDamagePopup();
    }
  }
</JS Pre-Apply As User>
Question, Elemental Exposure shows the weaknesses of the target the caster casts it on right?
 

DarthKai

Regular
Regular
Joined
Jan 11, 2023
Messages
76
Reaction score
14
First Language
English
Primarily Uses
Other
This works the same way as the original but needs <JS Pre-Apply> instead of <Before Eval>.

JavaScript:
<HRG Rate: 0%>

NOTE: You will need to add an if statement
to all DoT effects which use notetags in
order for this to work properly

For example, the Toxic effect won't be affected because it doesn't use the native regeneration functionality. You could incorporate HRG into such effects rather than using branching logic if you had a lot of them in your game.

JavaScript:
<JS Pre-Apply>
  const stateId = 69;
  if (target.isStateAffected(stateId)) {
    target.removeState(stateId);
  } else {
    target.addState(stateId);
  }
</JS Pre-Apply>

Replace 69 with the ID of your Mending state, which will have the following code:

JavaScript:
<JS Pre-Regenerate>
  const mpUpkeep = 5;
  if (origin.isAlive() && origin.mp >= mpUpkeep) {
    origin.gainMp(-mpUpkeep);
    origin.startDamagePopup();
    const regen = Math.floor(origin.mdf / 2);
    user.gainHp(regen);
    user.startDamagePopup();
  } else {
    origin.removeState(state.id);
  }
</JS Pre-Regenerate>

Just needs a <Custom Action Sequence>. The common event should look like this:
◆If:Script:BattleManager._action.subject().getAttackMotion().type !== 2
◆Plugin Command:VisuMZ_1_BattleCore, BTLOG: Display Action
◆Plugin Command:VisuMZ_1_BattleCore, MOVE: Move To Target(s)
: :Targets (Moving) = ["user"]
: :Targets (Destination) = ["all targets"]
: :Target Location = front base
: :Melee Distance = 24
: :Offset Adjustment = horz
: :Offset: X = 0
: :Offset: Y = 0
: :Duration = 20
: :Face Destination? = true
: :Movement Easing = Linear
: :Movement Motion = walk
: :Wait For Movement? = false

:Else
◆Plugin Command:VisuMZ_1_BattleCore, ACSET: Setup Action Set
: :Display Action = true
: :Immortal: On = true
: :Battle Step = true
: :Wait For Movement = true
: :Cast Animation = true
: :Wait For Animation = false

:End
◆Plugin Command:VisuMZ_1_BattleCore, MOTION: Motion Type
: :Targets = ["user"]
: :Motion Type = wait
: :Show Weapon? = true
◆Plugin Command:VisuMZ_1_BattleCore, MOVE: Wait For Movement
◆Plugin Command:VisuMZ_1_BattleCore, MOVE: Face Target(s)
: :Targets (facing) = ["user"]
: :Targets (destination) = ["current target"]
: :Face Away From? = false
◆Plugin Command:VisuMZ_1_BattleCore, MOTION: Motion Type
: :Targets = ["user"]
: :Motion Type = attack
: :Show Weapon? = true
◆Wait:10 frames
◆Plugin Command:VisuMZ_1_BattleCore, ANIM: Attack Animation
: :Targets = ["all targets"]
: :Mirror Animation = false
: :Wait For Animation? = true
◆If:Script:BattleManager._action.subject().hasWeapon($dataWeapons[1])
◆Plugin Command:VisuMZ_1_BattleCore, ELE: Force Elements
: :Elements = ["2"]
◆Plugin Command:VisuMZ_1_BattleCore, ANIM: Show Animation
: :Targets = ["all targets"]
: :Animation ID = 8
: :Mirror Animation = false
: :Wait For Animation? = false

:Else
◆If:Script:BattleManager._action.subject().hasWeapon($dataWeapons[2])
◆Plugin Command:VisuMZ_1_BattleCore, ELE: Force Elements
: :Elements = ["3"]
◆Plugin Command:VisuMZ_1_BattleCore, ANIM: Show Animation
: :Targets = ["all targets"]
: :Animation ID = 9
: :Mirror Animation = false
: :Wait For Animation? = false

:End

:End
◆Plugin Command:VisuMZ_1_BattleCore, MECH: Action Effect
: :Targets = ["all targets"]
◆Plugin Command:VisuMZ_1_BattleCore, ELE: Clear Element Changes
◆Plugin Command:VisuMZ_1_BattleCore, ANIM: Wait For Animation
◆Plugin Command:VisuMZ_1_BattleCore, ACSET: Finish Action
: :Immortal: Off = true
: :Wait For New Line = true
: :Wait For Effects = true
: :Clear Battle Log = true
: :Home Reset = true
: :Wait For Movement = true

Modify the ID of the weapon(s) being checked for and IDs of the associated elements according to your needs.

JavaScript:
<JS Pre-Apply>
  if (!this._sharedLifeRate) {
    this._sharedLifeRate = 0;
    const members = this.friendsUnit().aliveMembers();
    for (let i = 0; i < members.length; ++i) {
      const member = members[i];
      this._sharedLifeRate += member.hpRate();
    }
    this._sharedLifeRate /= members.length;
    this._sharedLifeRate += 0.15;
  }
</JS Pre-Apply>

<JS Post-Apply>
  if (target.isAlive()) {
    const targetHp = Math.floor(this._sharedLifeRate * target.mhp);
    const difference = targetHp - target.hp;
    if (difference > 0) {
      $gameTemp.requestAnimation([target], 41);
    } else if (difference < 0) {
      $gameTemp.requestAnimation([target], 54);
    }
    if (difference !== 0) {
      target.gainHp(difference);
      target.startDamagePopup();
    }
  }
</JS Post-Apply>

JavaScript:
<Reapply Rules: Ignore>

<JS On Add State>
  target._promisedDamage ??= 0;
</JS On Add State>

<JS Pre-Damage As Target>
  if (this.isHpEffect()) {
    target._promisedDamage ??= 0;
    if (value > 0) {
      target._promisedDamage += value;
    } else {
      target._promisedDamage += value * 2;
    }
    value = 0;
  }
</JS Pre-Damage As Target>

<JS On Erase State>
  target._promisedDamage ??= 0;
  if (target._promisedDamage > 0) {
    $gameTemp.requestAnimation([target], 11);
  } else {
    $gameTemp.requestAnimation([target], 41);
  }
  target.gainHp(-target._promisedDamage);
  delete target._promisedDamage;
  target.startDamagePopup();
</JS On Erase State>

JavaScript:
<JS Pre-Start Action>
  const paralyzeRate = 0.75;
  if (Math.random() < paralyzeRate) {
    $gameTemp.requestAnimation([user], 64);
    if (user.currentAction()) {
      user.useItem(user.currentAction().item());
    }
    this.setSkill(286);
    const logWindow = SceneManager._scene._logWindow;
    if ($dataStates[71].message3) {
      const msg = '<CENTER>' + user.name() + $dataStates[71].message3;
      logWindow.addText(msg);
      logWindow.refresh();
    }
  }
</JS Pre-Start Action>

This will need a "Paralyzed" skill with scope set to the user which does nothing, which in my project is 286. Adjust the ID as needed. Replace 71 with the ID of the Paralyze state.

Just needs a <Custom Action Sequence>. The common event should look like this:
◆If:Script:BattleManager._action.subject().getAttackMotion().type !== 2
◆Plugin Command:VisuMZ_1_BattleCore, BTLOG: Display Action
◆Plugin Command:VisuMZ_1_BattleCore, MOVE: Move To Target(s)
: :Targets (Moving) = ["user"]
: :Targets (Destination) = ["all targets"]
: :Target Location = front base
: :Melee Distance = 24
: :Offset Adjustment = horz
: :Offset: X = 0
: :Offset: Y = 0
: :Duration = 20
: :Face Destination? = true
: :Movement Easing = Linear
: :Movement Motion = walk
: :Wait For Movement? = false

:Else
◆Plugin Command:VisuMZ_1_BattleCore, ACSET: Setup Action Set
: :Display Action = true
: :Immortal: On = true
: :Battle Step = true
: :Wait For Movement = true
: :Cast Animation = true
: :Wait For Animation = false

:End
◆Plugin Command:VisuMZ_1_BattleCore, MOTION: Motion Type
: :Targets = ["user"]
: :Motion Type = wait
: :Show Weapon? = true
◆Plugin Command:VisuMZ_1_BattleCore, MOVE: Wait For Movement
◆Plugin Command:VisuMZ_1_BattleCore, MOVE: Face Target(s)
: :Targets (facing) = ["user"]
: :Targets (destination) = ["current target"]
: :Face Away From? = false
◆Plugin Command:VisuMZ_1_BattleCore, MOTION: Motion Type
: :Targets = ["user"]
: :Motion Type = attack
: :Show Weapon? = true
◆Wait:10 frames
◆Plugin Command:VisuMZ_1_BattleCore, ANIM: Attack Animation
: :Targets = ["all targets"]
: :Mirror Animation = false
: :Wait For Animation? = true
◆Script:BattleManager._action._targetHp = BattleManager._action.subject().opponentsUnit().members()[BattleManager._action._targetIndex].hp
◆Plugin Command:VisuMZ_1_BattleCore, MECH: Action Effect
: :Targets = ["all targets"]
◆If:Script:BattleManager._action.subject().opponentsUnit().members()[BattleManager._action._targetIndex].hp === BattleManager._action._targetHp
◆Plugin Command:VisuMZ_1_BattleCore, MECH: Add Buff/Debuff
: :Targets = ["user"]
: :Buff Parameters = []
: :Debuff Parameters = ["AGI"]
: :Turns = 5
◆Plugin Command:VisuMZ_1_BattleCore, ANIM: Show Animation
: :Targets = ["user"]
: :Animation ID = 54
: :Mirror Animation = false
: :Wait For Animation? = false
◆Plugin Command:VisuMZ_1_BattleCore, MOTION: Motion Type
: :Targets = ["user"]
: :Motion Type = dead
: :Show Weapon? = true
◆Plugin Command:VisuMZ_1_BattleCore, ANIM: Wait For Animation

:End
◆Script:delete BattleManager._action._targetHp
◆Plugin Command:VisuMZ_1_BattleCore, ACSET: Finish Action
: :Immortal: Off = true
: :Wait For New Line = true
: :Wait For Effects = true
: :Clear Battle Log = true
: :Home Reset = true
: :Wait For Movement = true

All states involved in this need a <No Death Clear> tag. The code that goes into the death state is the same as in the original, though I used "let" and "const" instead of "var".

JavaScript:
<JS Post-Damage As User>
  if (this.isHpEffect() && value > 0) {
    const actionElements = this.elements();
    const matchingElements = [2, 3, 4, 5, 6, 7, 8, 9];
    let condition = false;
    for (let i = 0; i < actionElements.length; ++i) {
      if (matchingElements.contains(actionElements[i])) {
        condition = true;
        break;
      }
    }
    if (condition) {
      const exposedState = 89;
      target.addState(exposedState);
    }
  }
</JS Post-Damage As User>

Modify matchingElements according to your own element types, and change 89 to the ID of your Expose Weakness state. That state should have the following code:

JavaScript:
<JS On Add State>
  target._exposedWeakness ??= 0;
  target._exposedWeakness = Math.min(4, target._exposedWeakness + 1);
  const counterText = "+" + (target._exposedWeakness * 5) + "%";
  target.setStateDisplay(state.id, counterText);
</JS On Add State>

<JS On Remove State>
  delete target._exposedWeakness;
  target.clearStateDisplay(89);
</JS On Remove State>

<JS Pre-Damage As Target>
  if (this.isHpEffect() && value > 0) {
    target._exposedWeakness = target._exposedWeakness || 0;
    let multiplier = 1;
    multiplier += target._exposedWeakness * 0.05;
    value *= multiplier;
    value = Math.ceil(value);
  }
</JS Pre-Damage As Target>

JavaScript:
<JS Pre-Damage As User>
  if (this.isMagical() && value !== 0) {
    value = Math.ceil(value * 1.5);
  }
</JS Pre-Damage As User>

This effect requires the tier 2 STB battle system for the instant tag.

JavaScript:
<Custom Action Sequence>
<STB Instant>

Action sequence for instant skills:
◆Plugin Command:VisuMZ_1_BattleCore, ACSET: Setup Action Set
: :Display Action = true
: :Immortal: On = true
: :Battle Step = true
: :Wait For Movement = true
: :Cast Animation = false
: :Wait For Animation = false
◆Plugin Command:VisuMZ_1_BattleCore, ACSET: All Targets Action Set
: :Dual/Multi Wield? = false
: :Perform Action = true
: :Wait Count = Sprite_Battler._motionSpeed
: :Action Animation = true
: :Wait For Animation = false
: :Action Effect = true
: :Immortal: Off = false
◆Plugin Command:VisuMZ_1_BattleCore, ACSET: Finish Action
: :Immortal: Off = true
: :Wait For New Line = true
: :Wait For Effects = true
: :Clear Battle Log = true
: :Home Reset = true
: :Wait For Movement = true

The action sequence for this is too long and specific to be worth transcribing, but if anyone really wants to see how it's done in VisuStella plugins PM me and I'll paste the common event.

JavaScript:
<JS Post-Damage As Target>
  if (target.result().hpDamage > 0) {
    let elements = this.elements();
    while (elements.length > 0) {
      const element = elements.shift();
      if (element >= 2 && element <= 9) {
        target.addState(element + 89);
        $gameTemp.requestAnimation([target], 53);
      }
    }
  }
</JS Post-Damage As Target>

The way I've set this up requires that all the elemental guard states and element types are in sequence. Change 89 to the ID of your first guard state minus the ID of the first element. If you haven't got yours in sequence, you'll need to modify this slightly.

JavaScript:
<JS Post-Apply>
  if (user.isActor() && target.isEnemy() && (target.isDead() || target.hp <= 0)) {
    const id = target.enemyId();
    const pool = [];
    pool.push($dataItems[7]);
    pool.push($dataItems[8]);
    pool.push($dataItems[9]);
    if (id === 1) {
      pool.push($dataWeapons[1]);
    } else if (id === 2) {
      pool.push($dataWeapons[2]);
      pool.push($dataWeapons[3]);
    } else if (id === 3) {
      pool.push($dataArmors[2]);
      pool.push($dataArmors[3]);
      pool.push($dataArmors[4]);
    }
    const item = pool[Math.randomInt(pool.length)];
    if (item) {
      $gameTemp.requestAnimation([target], 2);
      target.removeImmortal();
      SoundManager.playShop();
      $gameParty.gainItem(item, 1);
      const msg = '<CENTER>' + user.name() + ' acquired \\i[' + item.iconIndex + ']' + item.name + ' from ' + target.name() + '!';
      const logWindow = SceneManager._scene._logWindow;
      logWindow.addStealText(msg);
    }
  }
</JS Post-Apply>

Modify the pool array as necessary for your game.

JavaScript:
<JS On Add State>
  target._earthShieldHeal = Math.floor(origin.mat * 0.5);
  target.setStateDisplay(state.id, 9);
</JS On Add State>

<JS On Erase State>
  delete target._earthShieldHeal;
  target.clearStateDisplay(state.id);
</JS On Erase State>

<JS Pre-Damage As Target>
  if (this.isHpEffect() && value < 0) {
    value = Math.floor(value * 1.2);
    target.setStateDisplay(state.id, target.getStateDisplay(99) - 1);
    if (target.getStateDisplay(state.id) <= 0) {
      target.removeState(state.id);
    }
  }
</JS Pre-Damage As Target>

<JS Post-Apply As Target>
  if (target.isAlive() && target.result().hpDamage > 0) {
    const hpHealed = target._earthShieldHeal || 0;
    target.startDamagePopup();
    target.gainHp(hpHealed);
    target.startDamagePopup();
    target.setStateDisplay(state.id, target.getStateDisplay(99) - 1);
    if (target.getStateDisplay(state.id) <= 0) {
      target.removeState(state.id);
    }
  }
</JS Post-Apply As Target>

JavaScript:
<JS Pre-Start Battle>
  user._criticalProtect = false;
</JS Pre-Start Battle>

<JS Post-End Battle>
  user._criticalProtect = false;
</JS Post-End Battle>

<JS Post-Damage As Target>
  const crisis = 0.25;
  if ($gameParty.inBattle() && target.isAlive() && target.hpRate() <= crisis && !target._criticalProtect) {
    target._criticalProtect = true;
    target._criticalProtectTurns = 5;
    const turns = 5;
    target.addBuff(3, turns);
    $gameTemp.requestAnimation([target], 53);
  }
</JS Post-Damage As Target>

<JS Post-End Turn>
  if (target._criticalProtectTurns) {
    target._criticalProtectTurns--;
    if (target._criticalProtectTurns <= 0) {
      delete target._criticalProtectTurns;
      target._criticalProtect = false;
    }
  }
</JS Post-End Turn>

JavaScript:
<JS Pre-Apply>
  BattleManager.allBattleMembers().forEach(member => member.isStateAffected(102) ? member.removeState(102) : null);
</JS Pre-Apply>

The skill should have an effect to add the "Cyclone Bridge" state. Replace 102 with the ID of your Cyclone state proper. Cyclone Bridge should have the following code:

JavaScript:
<JS On Add State>
  target._cycloneTimes ??= 0;
  const turns = Math.max(5 - target._cycloneTimes * 2, 1);
  target.addState(102);
  target.setStateTurns(102, turns);
  target._cycloneTimes++;
</JS On Add State>

<JS On Erase State>
  delete target_cycloneTimes;
</JS On Erase State>

Again, replace 102 with the ID of your Cyclone state.

JavaScript:
<JS Pre-Apply>
  if (user.isActor()) {
    const allowed = [];
    allowed.push(1, 2, 3, 4);
    const skills = target.skills();
    for (let i = 0; i < skills.length; ++i) {
      const skill = skills[i];
      if (skill && allowed.contains(skill.stypeId) && !user.isLearnedSkill(skill.id)) {
        user.learnSkill(skill.id);
        const text = '<CENTER>' + user.name() + ' has learned \\i[' + skill.iconIndex + ']' + skill.name + ' from ' + target.name() + '!';
        const logWindow = SceneManager._scene._logWindow;
        logWindow._lines.push(text);
        $gameTemp.requestAnimation([user], 119);
      }
    }
  }
</JS Pre-Apply>

Modify the skill type IDs in the allowed array as needed.

JavaScript:
<JS Passive Condition>
  if ($gameParty.inBattle()) {
    condition = user.tp >= 80;
  } else {
    condition = false;
  }
</JS Passive Condition>

Add whatever buffs you wish to the state traits.

JavaScript:
<JS Passive Condition>
  if ($gameParty.inBattle()) {
    user._trance ??= false;
    condition = user._trance || user.tp === user.maxTp();
  } else {
    condition = false;
  }
  if (condition) {
    if (!user._trance) {
      $gameTemp.requestAnimation([user], 120);
    }
    user._trance = true;
  }
</JS Passive Condition>

<JS Pre-Regenerate>
  const tp = 10;
  user.gainTp(-tp);
  if (user.tp === 0) {
    user._trance = false;
  }
</JS Pre-Regenerate>

The setup of the Combo Attack skill should just add the Combo state, which should have the following code:

JavaScript:
<JS On Add State>
  user._comboStacks ??= 0;
  const stacks = user._comboStacks.clamp(0, 10);
  user.setStateDisplay(state.id, 'x' + stacks);
</JS On Add State>

<JS On Erase State>
  user._comboStacks = 0;
  user.setStateDisplay(state.id, 'x' + stacks);
</JS On Erase State>

<JS Pre-Damage As User>
  if (this.isPhysical() && value > 0 && !this.item().name.match('Combo')) {
    user._comboStacks ??= 0;
    let stacks = user._comboStacks.clamp(0, 10);
    const rate = 1 + stacks * 0.1;
    value = Math.ceil(value * rate);
    stacks++;
    stacks = stacks.clamp(0, 10);
    user.setStateDisplay(state.id, 'x' + stacks);
    user._comboStacks = stacks;
  }
</JS Pre-Damage As User>

Skills that use combo points should be set up similarly to this:

JavaScript:
<Custom Cost Text>
  2\i[160]
</Custom Cost Text>

<JS Skill Enable>
  user._comboStacks ??= 0;
  enabled = user._comboStacks >= 2;
</JS Skill Enable>

<JS Pre-start Action>
  user._comboStacks ??= 0;
  let stacks = user._comboStacks;
  stacks -= 2;
  stacks = stacks.clamp(0, 10);
  const comboStateId = 105;
  user.setStateDisplay(comboStateId, 'x' + stacks);
  user._comboStacks = stacks;
</JS Pre-start Action>

Replace 2 with whatever the combo cost is and 105 with the ID of your Combo state.

This requires the tier 3 Auto Skill Triggers plugin.

The state code should be:
JavaScript:
<JS Post-Damage As Target>
  if (value > 0) {
    target._tookDamage = true;
  }
</JS Post-Damage As Target>

<JS Post-End Action>
  target._tookDamage = false;
</JS Post-End Action>

And the skill code should be:

JavaScript:
<Auto Trigger: Certain Hit Enemy>
<Auto Trigger: Physical Enemy>
<Auto Trigger: Magical Enemy>
<Auto Trigger: Item Enemy>

<JS Skill Visible>
  visible = false;
</JS Skill Visible>

<JS Skill Enable>
  enabled = false;
  if (user.isActor()) {
    const potions = [];
    potions.push(7, 8, 9);
    for (let i = 0; i < potions.length; ++i) {
      const id = potions[i];
      if ($gameParty.numItems($dataItems[id]) > 0) {
        enabled = true;
        break;
      }
    }
  } else {
    enabled = true;
  }
</JS Skill Enable>

<JS Pre-Apply>
  if (target._tookDamage) {
    const potions = [];
    potions.push(7, 8, 9);
    for (let i = 0; i < potions.length; ++i) {
      const id = potions[i];
      if ($gameParty.numItems($dataItems[id]) > 0) {
        const item = $dataItems[id];
        if (user.isActor()) {
          $gameParty.loseItem(item, 1);
        }
        this.setItem(id);
        const text = '<CENTER>' + user.name() + ' uses \\i[' + item.iconIndex + ']' + item.name + '!';
        const logWindow = SceneManager._scene._logWindow;
        logWindow._lines.push(text);
        break;
      }
    }
  }
</JS Pre-Apply>

<Custom Action Sequence>

The action sequence is just
◆If:Script:BattleManager._action.subject()._tookDamage
◆Plugin Command:VisuMZ_1_BattleCore, ACSET: Setup Action Set
: :Display Action = true
: :Immortal: On = true
: :Battle Step = true
: :Wait For Movement = true
: :Cast Animation = false
: :Wait For Animation = false
◆Plugin Command:VisuMZ_1_BattleCore, ACSET: All Targets Action Set
: :Dual/Multi Wield? = false
: :Perform Action = true
: :Wait Count = Sprite_Battler._motionSpeed
: :Action Animation = true
: :Wait For Animation = false
: :Action Effect = true
: :Immortal: Off = false
◆Plugin Command:VisuMZ_1_BattleCore, ACSET: Finish Action
: :Immortal: Off = true
: :Wait For New Line = true
: :Wait For Effects = true
: :Clear Battle Log = true
: :Home Reset = true
: :Wait For Movement = true

:End

Note that the state needs the "Add Skill: Auto Potion" trait for this to work. Replace 7, 8, 9 with the IDs of the potions you want to use with the effect, in the order they should be prioritised.

If you want to limit the effect as per the original T&T, you'll also need the tier 3 Limited Skill Uses plugin. Add a <Limited Uses: x> tag to the Auto Potion skill.

JavaScript:
<JS Post-Start Action>
  if (!$gameTemp._chainAction) {
    $gameTemp._chainAction = user.currentAction();
  } else {
    delete $gameTemp._chainAction;
  }
</JS Post-Start Action>

<JS Pre-End Action>
  if ($gameTemp._chainAction) {
    const action = $gameTemp._chainAction;
    if (action && action.isSkill() && action.isMagical()) {
      const skill = action.item();
      if (user.canPaySkillCost(skill)) {
        user.setAction(0, action);
      }
    }
  }
</JS Pre-End Action>

<JS On Erase State>
  delete $gameTemp._chainAction;
</JS On Erase State>

The Living Dead state itself just needs a <No Death Clear> tag. The Walking Dead state's code is:

JavaScript:
<JS Pre-Regenerate>
  if (target.isStateAffected(state.id)) {
    if (target.hp <= 0) {
      target.setHp(1);
    }
  }
</JS Pre-Regenerate>

<JS On Add State>
  target._walkingDeadHp = target.mhp;
  target._walkingDeadFailed = false;
  $gameTemp.requestAnimation([target], 65);
  target.setStateDisplay(state.id, target._walkingDeadHp);
</JS On Add State>

<JS On Erase State>
  target._walkingDeadHp ??= target.mhp;
  if (target._walkingDeadHp > 0) {
    target._walkingDeadFailed = true;
    target.setHp(0);
  }
</JS On Erase State>

<JS Post-Damage As Target>
  target._walkingDeadHp ??= target.mhp;
  if (value < 0) {
    target._walkingDeadHp += value;
    user.setStateDisplay(state.id, Math.max(0, target._walkingDeadHp));
  }
  if (target.hp <= 0) {
    target.setHp(1);
  }
</JS Post-Damage As Target>

And in the Death state:

JavaScript:
<JS On Add State>
  if (target.isStateAffected(108) && !target._walkingDeadFailed) {
    target.removeState(1);
    target.removeState(108);
    target.addState(109);
    user.setHp(1);
  }
</JS On Add State>

Replace 108 with the ID of the Living Dead state, and 109 with the ID of the Walking Dead state.

This effect can't be replicated due to not having the functionality of Selection Control.

The state setup is the same as in the original, as there's no code involved. In any skill which you want Blood Magic to affect, you'd put the following:

JavaScript:
<JS MP Cost>
  if (user.isStateAffected(110)) {
    cost = 0;
  }
</JS MP Cost>
<JS HP Cost>
  if (user.isStateAffected(110)) {
    cost = skill.mpCost * 2;
  }
</JS HP Cost>

JavaScript:
<JS On Add State>
  target._healingFateDamage = 0;
</JS On Add State>

<JS On Erase State>
  delete target._healingFateDamage;
</JS On Erase State>

<JS Post-Damage As Target>
  if (this.isHpEffect() && value > 0) {
    target._healingFateDamage += value;
    if (target._healingFateDamage >= target.mhp * 0.2) {
      target.removeState(state.id);
      const members = origin.friendsUnit().aliveMembers();
      const hpHealed = origin.mdf * 2;
      for (let i = 0; i < members.length; ++i) {
        const member = members[i];
        if (member) {
          member.gainHp(hpHealed);
          $gameTemp.requestAnimation([member], 46);
          member.startDamagePopup();
        }
      }
    }
  }
</JS Post-Damage As Target>

The skill code should be:

JavaScript:
<JS Pre-Damage>
  target._currentHp = target.hp;
</JS Pre-Damage>

<JS Post-Damage>
  if (target._currentHp && target.hp <= 0) {
    const damage = value - target._currentHp;
    if (damage > 0) {
      const overkillStateId = 112;
      user.addState(overkillStateId);
      user._overkillBonus = damage;
      $gameTemp.requestAnimation([user], 51);
    }
  }
  delete target._currentHp;
</JS Post-Damage>

Replace 112 with the ID of your Overkill state, which should have the following code:

JavaScript:
<JS Pre-Damage As User>
  if (this.isHpEffect() && value > 0) {
    user._overkillBonus ??= 0;
    value += Math.min(value * 5, user._overkillBonus);
    $gameTemp.requestAnimation([target], 13);
  }
</JS Pre-Damage As User>

JavaScript:
<JS Pre-Start Action>
  user._reverenceMp = user.mp;
</JS Pre-Start Action>

<JS Pre-Apply As User>
  if (user._reverenceMp) {
    const difference = user._reverenceMp - user.mp;
    if (difference > 0) {
      const hp = Math.ceil(difference * 20);
      user.gainHp(hp);
      user.startDamagePopup();
    }
  }
</JS Pre-Apply As User>
Have I added in Elemental Exposure correctly(It's Kill sight here)?
 

Attachments

  • Screenshot_20230214_020657.png
    Screenshot_20230214_020657.png
    83.2 KB · Views: 6
  • Screenshot_20230214_020731.png
    Screenshot_20230214_020731.png
    142.4 KB · Views: 7
  • Screenshot_20230214_020758.png
    Screenshot_20230214_020758.png
    64.5 KB · Views: 5
  • Screenshot_20230214_020828.png
    Screenshot_20230214_020828.png
    89.9 KB · Views: 7

Trihan

Speedy Scripter
Regular
Joined
Apr 12, 2012
Messages
6,838
Reaction score
7,852
First Language
English
Primarily Uses
RMMZ
So, this may be a bit of a tall order but the newest Visustella update added selection control to its Battle Core plugin via Notetag. Could this be enough to actually implement the plugins that weren't possible before due to the lack of selection control mechanics?
Yes, I'll be looking at those soon.

Question, Elemental Exposure shows the weaknesses of the target the caster casts it on right?
Correct. It displays the +/- percentage in the state icon.

Have I added in Elemental Exposure correctly(It's Kill sight here)?
No, you haven't. These go in notetags on the state, there's no common event involved.
 

DarthKai

Regular
Regular
Joined
Jan 11, 2023
Messages
76
Reaction score
14
First Language
English
Primarily Uses
Other
I put in the code in the notes like you told me to, but when I tested it out, it's weakness never popped up in the text box.
 

Dark_Ansem

Regular
Regular
Joined
Jun 16, 2020
Messages
652
Reaction score
162
First Language
English
Primarily Uses
RMMZ
Any luck using the new selection functions in getting some of the un-porteable tips working?
 

Trihan

Speedy Scripter
Regular
Joined
Apr 12, 2012
Messages
6,838
Reaction score
7,852
First Language
English
Primarily Uses
RMMZ
Any luck using the new selection functions in getting some of the un-porteable tips working?
I haven't had the time yet, hoping to do that in the next couple of weeks.
 

Latest Threads

Latest Profile Posts

There the rituals are now completely in place and the player can free three trapped souls from the mansion, and face the good ending boss.
TSR
Capture d’écran, le 2023-12-03 à 13.24.07.png
No screen shots from my main project today. I've been spending all my game dev time of that jam entry...
Have a Ho Ho Ho week! :cutesmile:
Have you found your favourite plant combination yet?
1701625459444.png
Me with the fireplace, a space heater, and a heated blanket. My preferred lizard temperature.

I'm gonna riff on Macross's "Deculture" and adopt "Descope" as my motto! :wub God knows I'm gonna need it...

As an aside, did any of ya sweeties watch Macross Delta and if so, was it good, bad, or horrible?

Forum statistics

Threads
136,719
Messages
1,269,078
Members
180,434
Latest member
Cheesymud
Top